我正在将资源加载到统一中,但我不知道如何从内存中释放它们。
我有一个脚本可以加载这样的预览图像:
//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++;
}
但每次运行代码时,我的内存使用量都会增加一倍。如何在第二次执行时从内存中释放精灵?
答案 0 :(得分:3)
你做不到。有人会说GC.Collect()
,但这不是这里的情况。您的代码可以进行优化以减少内存分配。
<强> 1 即可。导致大部分内存分配的原因是Sprite.Create
。它分配内存非常糟糕。解决方案是改变您的设计。使用RawImage
数组而不是Sprite
数组,这种不必要的内存分配将会消失。
2 。Texture2D texture = new Texture2D(100, 100);
也会分配内存。由于 100 总是 100 ,因此您可以重复使用它。将其设为全局,并在开始时调用一次新的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循环中索引,但当前代码没问题。