Unity System.Drawing 内部缓冲区溢出异常

Unity System.Drawing Internal Buffer Overflow Exception

目标

从 URL 获取统一工作的 gif,我目前正在使用 WWW class。我目前正在获取一个 byte[] 并将其转换为 System.Drawing.Image。 这在编辑器中有效,但在任何构建中都无效

错误:

"Type Load Exception: Could not load type" System.IO.InternalBufferOverflowException 来自第 111 行的程序集 "System.Drawing.Image"

为什么?

它与 System.Drawing.Image.FromStream 内置方法有关,Unity 出于某种原因不喜欢它。其他选项是.FromFile 和.FromHBitMap,我不知道如何使用HBitMap 但回到我原来的计划,.FromFile 对我来说是无法使用的。

完整代码

using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using UnityEngine;
using System.IO;
using UnityEngine.UI;
using System.Collections;

public class AnimatedGifDrawerBack : MonoBehaviour
{
    public string loadingGifPath;
    public float speed = 1;
    public Vector2 drawPosition;
    public string pName;

    public float width;
    public float height;
    public float percentage;
    public GameObject positionPlaceHolderGO;
    public Vector2 positionPlaceHolder;
    public Text debugText;
    private SpriteImageArray sia;
    private string url;
    private WWW www;
    public bool finishedWWW = false;
    public bool hasWWW = false;
    public bool canOnGUI = false;

    List<Texture2D> gifFrames = new List<Texture2D>();

    void Start()
    {


        percentage = 1.3f;
        positionPlaceHolderGO = GameObject.FindGameObjectWithTag("PBLPlace");
        positionPlaceHolder = positionPlaceHolderGO.transform.position;

    }

    void Update()
    {
        while (hasWWW == false)
        {
            Debug.Log("in while loop");
            if (this.GetComponent<PokemonCreatorBack>().name == "")
            {

            }
            else
            {
                debugText.text = "Name Found";
                url = "www.pkparaiso.com/imagenes/xy/sprites/animados-espalda/" + this.GetComponent<PokemonCreatorBack>().PokemonName.ToLower() + ".gif";

                StartCoroutine(WaitForRequest(positionPlaceHolderGO, url));
                hasWWW = true;
                debugText.text = "hawWWW = true";
            }
        }
    }

    void OnGUI()
    {
        height = (float)Screen.height - 80f / percentage;

        //GUI.DrawTexture (new Rect (Screen.width-width, Screen.height - height, gifFrames [0].width * percentage, gifFrames [0].height * percentage), gifFrames [(int)(Time.frameCount * speed) % gifFrames.Count]);
        if (canOnGUI)
            GUI.DrawTexture(new Rect(positionPlaceHolder.x, positionPlaceHolder.y, gifFrames[0].width * percentage, gifFrames[0].height * percentage), gifFrames[(int)(Time.frameCount * speed) % gifFrames.Count]);

    }

    IEnumerator WaitForRequest(GameObject go, string url)
    {
        www = new WWW(url);
        yield return www;
        if (www.error == null)
        {
            Debug.Log("WWW Ok!: " + www.texture.name);
        }
        else
        {
            Debug.Log("WWW Error: " + www.error);
        }
        debugText.text = "finishedWWW = true";
        finishedWWW = true;
    }

    public System.Drawing.Image ByteArrayToImage(byte[] byteArrayIn)
    {
        if (finishedWWW == false)
        {
            Debug.Log("Called too early");
        }
        if (byteArrayIn == null)
        {
            Debug.Log("Null byte array");
            return null;
        }
        Debug.Log("Bytra array in length: " + byteArrayIn.GetLongLength(0));
        MemoryStream ms = new MemoryStream(byteArrayIn);
        System.Drawing.Image returnImage = System.Drawing.Image.FromStream(ms);     //MAIN SOURCE OF ERROR HERE
        finishedWWW = true;
        debugText.text = "System.Image Created";
        return returnImage;
    }

    public void loadImage()
    {
        Debug.Log("Called Load Image BACK");
        debugText.text = "Called Load Image BACK";
        System.Drawing.Image gifImage = ByteArrayToImage(www.bytes);


        FrameDimension dimension = new FrameDimension(gifImage.FrameDimensionsList[0]);
        int frameCount = gifImage.GetFrameCount(dimension);
        for (int i = 0; i < frameCount; i++)
        {
            gifImage.SelectActiveFrame(dimension, i);
            Bitmap frame = new Bitmap(gifImage.Width, gifImage.Height);
            System.Drawing.Graphics.FromImage(frame).DrawImage(gifImage, Point.Empty);
            Texture2D frameTexture = new Texture2D(frame.Width, frame.Height);
            for (int x = 0; x < frame.Width; x++)
                for (int y = 0; y < frame.Height; y++)
                {
                    System.Drawing.Color sourceColor = frame.GetPixel(x, y);
                    frameTexture.SetPixel(frame.Width - 1 + x, -y, new Color32(sourceColor.R, sourceColor.G, sourceColor.B, sourceColor.A)); // for some reason, x is flipped
                }
            frameTexture.Apply();
            gifFrames.Add(frameTexture);
        }
        Debug.Log("Starting ON GUI!");
        debugText.text = "Starting OnGUI";
        canOnGUI = true;
    }
}

想法

  1. byteArrayIn.GetLongLength(0) returns最多八万个。
  2. 最后一条调试语句称为图像加载返回。
  3. 如果需要的话我会自己写一个流光,如果有需要谁能指点我写的方向。
  4. 我认为主要的解决方法是处理 Image.FromStream()。
  5. 场景中有两个。

欢迎所有想法或解决方案,我真的只是希望我知道如何解决这个错误,以便我可以与 Unity 社区分享更多。

今天早上我们遇到了同样的问题。

该应用在 System.IO 命名空间中找不到 System.Drawing.Image.

所需的类型

缺少的类型显然已从构建过程中打包的 system.dll 中删除。

要解决此问题,您需要复制生成的统一 System.dll 并将其替换为原始单声道 System.dll

在您的构建中,将 projectName_Data\Managed\System.dll 替换为在 Unity 的单声道安装文件夹中找到的 System.dll

Editor\Data\Mono\lib\mono.0(相对于Unity安装文件夹的根目录)

希望对您有所帮助!