When I was writing code that updates the Texture of a GameObject every frame and draws it like a movie, an event that crashes abnormally in the native environment occurred. The method investigated at that time and the cause are summarized.
I knew that it was memory related because I had issued the following error in advance. (WebGL)
Uncaught RangeError : Maximum Call Stack Size Exceeded
Next, check the memory usage from Profiler and confirm that the Unity memory is over 3GB. (The pace of increase was several tens of MB per second)
Furthermore, when checking what is consuming memory from Detailed in the memory view, it was found that Texture2D allocates 2.3MB of memory for each frame as shown in the image.
I knew only one place where Texture2D was generated so much, so I decided to check the corresponding code.
The corresponding code is as follows.
//frame is a unique class that holds texture information in binary var texture2D = new Texture2D(frame.Width, frame.Height, TextureFormat.RGBA32, false); texture2D.wrapMode = TextureWrapMode.Clamp; texture2D.LoadRawTextureData(frame.Buffer); texture2D.Apply(); material.mainTexture = texture2D;
The problem here is the part of
new Texture2D (). The memory allocated this time is referenced by
material.mainTexture in the current frame, but
material.mainTexture is referenced by another in the next frame. Holds. Therefore, the memory area of
Texture2D allocated in the previous frame is no longer referenced from anywhere, and since it is Unity memory, GC is not performed and it leaks as it is.
The solution is to manually release the memory of
Texture2D used in the previous frame.
Memory release of assets used in Unity can be done with
The actual modified code is as follows.
var texture2D = new Texture2D(frame.Width, frame.Height, TextureFormat.RGBA32, false); texture2D.wrapMode = TextureWrapMode.Clamp; texture2D.LoadRawTextureData(frame.Buffer); texture2D.Apply(); //Added this Destroy(material.mainTexture); material.mainTexture = texture2D;
This successfully eliminated the memory leak and prevented the app from crashing in the native environment.
If you say “the app is heavy or crashes due to memory”, first check “Profiler”.
Even if you hit the dark clouds and fix it, it will only cost you and it will not necessarily improve.
Optimization using Profiler is summarized in Notes from watching the video of “[Unite 2017 Tokyo] Technologies to remember before optimization”. If you have no connection at all, you should read it.
- We would appreciate it if you could comment if there is a more efficient method of investigation or solution.