Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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;
like image 975
aCuria Avatar asked Sep 14 '25 21:09

aCuria


1 Answers

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();
}
like image 105
Programmer Avatar answered Sep 17 '25 12:09

Programmer