2

目标

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

错误:

第 111 行的程序集“System.Drawing.Image”中的“类型加载异常:无法加载类型”System.IO.InternalBufferOverflowException

为什么?

它与 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) 最多返回 80,000。
  2. 最后通过的调试语句称为 Image Loading BACK。
  3. 如有必要,我将编写自己的火焰流光,如果有必要,有人可以指出我的写作方向。
  4. 我认为主要的解决方法是处理 Image.FromStream()。
  5. 场景中有两个。

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

4

1 回答 1

3

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

System.IO该应用程序未在所需的命名空间中找到类型System.Drawing.Image.

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

要解决此问题,您需要复制并替换System.dll使用原始 mono生成的 unity System.dll

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

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

希望能帮助到你!

于 2015-10-12T10:33:30.457 回答