Reputation: 23
I'm getting a serious memory leak when assigning textures at runtime.
When useNewArray is true, Task manager shows that Unity's memory usage grows by ~20 MBs / second.
The full (183k zipped) project can be downloaded here: https://goo.gl/axFJDs
Here's my code:
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class testMemory : MonoBehaviour {
public bool useNewList = false;
Texture2D newTexture;
public byte color;
List<Color> newColors;
List<byte> staticPixelColorsList;
Color tempColor = Color.white;
// Use this for initialization
void Start () {
newTexture = new Texture2D(0,0);
newColors = new List<Color>();
staticPixelColorsList = new List<byte>(120000);
GetComponent<Renderer>().material.mainTexture = newTexture;
}
// Update is called once per frame
void Update () {
// Make sure we're using different colors for every frame
color = (byte)((Time.time*255) % 255);
if(useNewList)
{
// This option causes a memory leak, but it's the one I need
// because I'm getting the texture data from an external source
int newWidth = Random.Range(200,400);
int newHeight = Random.Range(200,400);
// Create a new list each time
List<byte> newPixels = new List<byte>(newWidth * newHeight);
for(int i = 0; i < newWidth * newHeight; i++)
{
newPixels.Add ((byte)(color * i / 120000f));
}
setTexture(newPixels, newWidth, newHeight);
// Clear the list (yeah, right)
newPixels.Clear ();
}
else
{
// Use the same list, but assign new colors
for(int i = 0; i < 120000; i++)
{
staticPixelColorsList.Add ((byte)(color * i / 120000f));
}
setTexture(staticPixelColorsList, 300, 400);
staticPixelColorsList.Clear ();
}
}
void setTexture(List<byte> inputPixels, int inputWidth, int inputHeight)
{
newTexture.Resize(inputWidth, inputHeight);
float colorValue;
// Convert input value to Unity's "Color"
for(int n = 0; n < newTexture.width * newTexture.height ; n++)
{
colorValue = inputPixels[n] / 255.0f;
tempColor.r = tempColor.g = tempColor.b = colorValue;
newColors.Add (tempColor);
}
// Actually set the texture pixels
newTexture.SetPixels(newColors.ToArray());
newTexture.Apply();
newColors.Clear();
}
}
Thanx in advance.
Upvotes: 0
Views: 1963
Reputation: 23
Apparently this is a bug with Texture2D.Apply(). It's so deep, Unity's profiler did not show the leak, but external tools did. Unity have acknowledged the problem and are seeking out a solution. No date was given. Thanks for the help :-)
Upvotes: 1
Reputation: 324
According to this MSDN Article, the List<T>.Clear
method resets the Count
property to 0 and releases all references to elements of the collection.
However, the capacity remains unchanged. Therefore, the same amount of memory stays allocated. To release this memory, the TrimExcess
method should be called, or the Capacity
property manually set.
Maybe instead of making a new newPixels
list each time the Update
method is called you could create this list outside of the function (perhaps in the class declaration) and refill it each time the Update
method is called? Clearing would be optional, since every call, the contents would be overwritten. This could also improve performance, since your code won't have to release every member of the collection at the end of every update.
Upvotes: 2