c# - Unity内存问题资源图片

标签 c# memory unity3d memory-leaks

我正在将资源加载到 unity 中,但我不知道如何从内存中释放它们。

我有一个脚本可以像这样加载预览图像:

//load the 12 images
        while (currentPreviewNumber < 12) {
            Debug.Log (currentPreviewNumber);
            byte[] tBytes = System.IO.File.ReadAllBytes (Application.persistentDataPath + "/" + currentPreviewNumber + ".jpg");
            Texture2D texture = new Texture2D (100, 100);
            texture.LoadImage (tBytes);

            sprites [currentPreviewNumber] = Sprite.Create (texture, new Rect (0, 0, mCamera.width, mCamera.height),
                new Vector2 (0.5f, 0.5f),
                40);

            currentPreviewNumber++;
        }

但每次我运行代码时,我的内存使用量都会翻倍。第二次执行时如何从内存中释放 Sprite ?

最佳答案

你不能。有人会说 GC.Collect() 但这里不是这种情况。可以优化您的代码以减少内存分配。

1。造成这些内存分配的大部分原因是 Sprite.Create。它分配内存太糟糕了。解决方案是更改您的设计。使用 RawImage 数组而不是 Sprite 数组,这种不必要的内存分配就会消失。

2.Texture2D texture = new Texture2D(100, 100); 也分配内存。因为它始终是 100 x 100,所以您可以重复使用它。将其设为全局并在开始时调用一次 new new Texture2D(100, 100);。这节省了内存分配。

3.使用StringBuilder拼接Application.persistentDataPath + "/"+ currentPreviewNumber + ".jpg"

4.Application.persistentDataPath 分配内存。将其存储在 Start() 函数中的临时值中,而不是在 while 循环中重复调用它。

解决方案 1:

public RawImage defaultRawImage;
RawImage[] rawImages;
Texture2D texture = null;
int currentPreviewNumber = 0;
string appPath;
System.Text.StringBuilder imagePath;

void Start()
{
    appPath = Application.persistentDataPath;

    //Init Texture 2D
    texture = new Texture2D(100, 100, TextureFormat.RGB24, false);

    //Init All 12 Raw Images
    rawImages = new RawImage[12];
    for (int i = 0; i < rawImages.Length; i++)
    {
        rawImages[i] = Instantiate(defaultRawImage) as RawImage;
    }

    //Init String Builder
    imagePath = new System.Text.StringBuilder(300);
}

void loadPreviewOptimized()
{
    while (currentPreviewNumber < 12)
    {
        //Debug.Log(currentPreviewNumber);
        imagePath.Capacity = 0;
        imagePath.Append(appPath).Append("/").Append(currentPreviewNumber).Append(".jpg");

        //Read File
        byte[] tBytes = System.IO.File.ReadAllBytes(imagePath.ToString());
        texture.LoadImage(tBytes);

        rawImages[currentPreviewNumber].texture = texture;
        currentPreviewNumber++;
    }
}

byte[] tBytes = System.IO.File.ReadAllBytes(imagePath.ToString()); 代码分配内存以返回字节。要摆脱它,请将 tBytes 设为全局变量,然后只分配一次内存。当你想用 File.ReadAllBytes 停止内存分配时,下面是一个完整的代码。

解决方案 2:

public RawImage defaultRawImage;
RawImage[] rawImages;
Texture2D texture = null;
int currentPreviewNumber = 0;
string appPath;
System.Text.StringBuilder imagePath;
byte[] tBytes;

void Start()
{
    appPath = Application.persistentDataPath;

    //Init Texture 2D
    texture = new Texture2D(100, 100, TextureFormat.RGB24, false);

    //Init All 12 Raw Images
    rawImages = new RawImage[12];
    for (int i = 0; i < rawImages.Length; i++)
    {
        rawImages[i] = Instantiate(defaultRawImage) as RawImage;
    }

    //Init String Builder
    imagePath = new System.Text.StringBuilder(300);
    tBytes = new byte[90000];
}


void loadPreviewOptimized()
{
    while (currentPreviewNumber < 12)
    {
        //Debug.Log(currentPreviewNumber);

        //Reset Capacity before Reading
        imagePath.Capacity = 0;
        imagePath.Append(appPath).Append("/").Append(currentPreviewNumber).Append(".jpg");

        //Read File
        using (System.IO.FileStream myfile = System.IO.File.Open(imagePath.ToString(), System.IO.FileMode.Open, System.IO.FileAccess.Read, System.IO.FileShare.ReadWrite))
        {
            //Check if array size is enough before writing
            if (tBytes.Length >= myfile.Length)
            {
                //OK (Write file to tBytes array)
                myfile.Read(tBytes, 0, (int)myfile.Length);
                texture.LoadImage(tBytes);
            }
            else
            {
                //NOT OK (Resize array size)
                tBytes = new byte[myfile.Length];

                //Write file to tBytes array
                myfile.Read(tBytes, 0, (int)myfile.Length);
                texture.LoadImage(tBytes);
            }

            rawImages[currentPreviewNumber].texture = texture;
            currentPreviewNumber++;
        }
    }
}

它现在分配的内存是 10.0kb,这很好。如果您想对此进行更多优化,而不是在 while 循环中使用 StringBuilder 生成字符串,而是在 Start 函数中执行一次并将这些字符串路径存储到字符串数组中稍后可以在 while 循环中与索引一起重新使用,但当前代码没问题。

关于c# - Unity内存问题资源图片,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37495499/

相关文章:

c# - 获取 WPF 控件的当前大小

c# - MS 图表烛台 如何设置尾部颜色

c++ - C++ 如何从内存缓冲区中读取数据

C++ Boost ASIO async_send_to 内存泄漏

c# - 在 Unity 5.0 中创建 Wp8 Unity 插件

c# - 更改场景时 WebCamTexture 崩溃

c# - 如何检查用户是否已在 AdMob for Unity 中完成视频?

c# - 炮塔射击

android - 如何访问类加载器/App Linearalloc 类信息大小?

c# - CoInitialize() 是否总是在每个 .Net Framework/.Net Core 线程上隐式调用?