Reputation: 7215
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
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
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