aCuria
aCuria

Reputation: 7215

What causes Unity Memory Leaks?

I am having memory leaks with Unity with the following code:

Behavior: in runtime, Unity eventually uses > 64GB of RAM and crashes (Thats all this machine has)

Scene: I only have one plane in my scene with the below code.

How do I fix this? I dont think I want a weak reference here, (or at least in C++ I wont use a weak_ptr in this scenario, maybe a unique_ptr). I just want the memory to be deallocated when objects fall out of scope.

void Start () {
    frameNumber_ = 0;

    // commented code leaks memory even if update() is empty
    //WebCamDevice[] devices = WebCamTexture.devices;
    //deviceName = devices[0].name;
    //wct = new WebCamTexture(deviceName, 1280, 720, 30);
    //GetComponent<Renderer>().material.mainTexture = wct;
    //wct.Play();

    wct = new WebCamTexture(WebCamTexture.devices[0].name, 1280, 720, 30);
    Renderer renderer = GetComponent<Renderer>();
    renderer.material.mainTexture = wct;
    wct.Play();
}

// Update is called once per frame
// This code in update() also leaks memory
void Update () {
    if (wct.didUpdateThisFrame == false)
        return;

    ++frameNumber_;

    Texture2D frame = new Texture2D(wct.width, wct.height);
    frame.SetPixels(wct.GetPixels());
    frame.Apply();

    return;

Upvotes: 4

Views: 12112

Answers (2)

JMcNeil
JMcNeil

Reputation: 11

Archaic topic but I found something interesting. I used to have this in my code:

            downloadedTexture = DownloadHandlerTexture.GetContent(www);
        m_PictureScreen.GetComponent<RawImage>().texture = downloadedTexture;

this caused huge problems with memory leaks, app went over 8gb with every iteration of that. I my case that could ramp up to thousands of files per day. I solved it by using this line before:

Texture2D.Destroy(m_PictureScreen.GetComponent<RawImage>().texture);

Not sure how but it worked and memory leaks do not exist now.

Upvotes: 1

Programmer
Programmer

Reputation: 125455

See this:

Texture2D frame = new Texture2D(wct.width, wct.height);

You are crating new Texture2D almost every frame or when didUpdateThisFrame is true. This is very expensive and most of the time is not even freed by Unity. You only need to create one Texture2D then re-use it in the Update function. Make the frame variable a global variable then initialize it once in the Start function.


By doing this, you will likely run into new problem when camera image height/width changes causing frame.SetPixels(wct.GetPixels()); to fail with an exception. To fix this, check when the camera texture size changes then automatically resize your frame Texture. This check should be done in the Update function before frame.SetPixels(wct.GetPixels());.

if (frame.width != wct.width || frame.height != wct.height)
{
    frame.Resize(wct.width, wct.height);
}

Your final code should looks something like this:

int frameNumber_ = 0;
WebCamTexture wct;
Texture2D frame;

void Start()
{
    frameNumber_ = 0;

    wct = new WebCamTexture(WebCamTexture.devices[0].name, 1280, 720, 30);
    Renderer renderer = GetComponent<Renderer>();
    renderer.material.mainTexture = wct;
    wct.Play();

    frame = new Texture2D(wct.width, wct.height);
}

// Update is called once per frame
// This code in update() also leaks memory
void Update()
{
    if (wct.didUpdateThisFrame == false)
        return;

    ++frameNumber_;

    //Check when camera texture size changes then resize your frame too
    if (frame.width != wct.width || frame.height != wct.height)
    {
        frame.Resize(wct.width, wct.height);
    }

    frame.SetPixels(wct.GetPixels());
    frame.Apply();
}

Upvotes: 7

Related Questions