Unable to determine cause of memory leak in Unity when using Addressables. Can anyone give suggestions on what the cause might be?

I’m creating a simple bullet hell game for Android and I ran into an issue when diagnosing my game using the Memory Profiler where memory usage was increasing after each play-through. I had calls to unload and/or release any assets that were being used but that didn’t seem to make a difference as memory still kept increasing.

Since I couldn’t determine what the exact cause for the leak was, I decided to create a test version of my game on a different branch where everything from the game would be stripped down except for some assets in the gameplay levels.

The main menu uses only Unity’s built in resources and therefore no assets from any asset bundles that need to be downloaded (double-checked groups for addressables just to be sure). It also has 3 buttons that will manually destroy or release any objects that are deemed as addressables or do a Resources.UnloadUnusedAssets() call. Below is a picture of the main menu:

Below is a snapshot of the end of the game after traversing through two game play scenes. Again, there are buttons that will destroy and release any objects that are deemed as addressables or do a Resources.UnloadUnusedAssets() call.

Here is the snapshot from Unity’s memory profiler. As you can see there is a big difference in Texture2D which makes sense because the gameplay levels use textures, materials and graphics but the main menu doesn’t.

However, the strange thing happens when I return to the main menu. As you can see in the memory profiler, nothing is being used in terms of Unity Objects. However, Graphics and Untracked memory keep building for some reason. I even pressed the button that calls Resources.UnloadUnusedAssets() which in theory should unload all the assets I’ve used in the gameplay scenes since they’re unused but it did nothing. In fact, my memory in one gameplay increases 28MB.


Then I decided to do one more play-through and once I returned to the main menu, the memory usage increased another 21MB instead of unloading unused assets from the gameplay scene. Again, nothing unusual when comparing the Unity Objects being used from the screenshot of the main menu scene at the start of the app running vs. the main menu scene after two play-throughs.

However, the untracked and graphics memory keeps increasing for some weird reason and there’s even an error with Graphics memory addresses:

So this means there was a ~47MB increase in memory usage when doing two play-throughs and going back to the main menu which doesn’t make sense if assets are being unloaded because at least we would see a slight decrease in memory usage when returning to the main menu but the memory usage never decreases as it just keeps going up.

I’ve tried unloading assets first in a controlled coroutine before unloading the whole scene using Addressables.UnloadSceneAsync(). I’ve tried both Addressables.Release() and Addressables ReleaseHandle() on objects that are not going to be used anymore. I’ve even tried manually releasing assets through calls like GC.Collect() and Resources.UnloadUnusedAssets() after a new scene finished loading or after returning to the main menu but nothing I do reduces memory.

I think I was pretty thorough when writing the code used for managing my app’s memory. What might the issue be in this case? Could there be a chance that the memory readings are giving false information? What are the other possibilities that this memory leak happens? I’ve spent a week dissecting and simplifying my project in order to figure out the problem but to no avail.

For some reason the tags didn’t appear when I posted this. This is a problem involving the Memory Profiler, Addressables system, Scene Management, and Asset Management.

The Graphics > <No Name> bug is fixed if you update to the latest release of the package and the latest patch release of the major version of the engine that you’re on. But that only fixed the rooting of those resources to the Graphics Driver who retains some formerly allocated resources as buffers for reuse.

Since you’re not comparing the first re-entry to the main menu scene to the second one, your Graphics memory doesn’t actually increase between these. It increases once by 16 MB which is then retained as a buffer, reused on entering the gameplay scene again, and then retained as reusable buffer on entering the main menu scene a second time. So that’s totally fine and not a leak at all.

That graphics memory is what our engine code submitted to the Graphics Driver/Graphics API (i.e. Vulkan, OpenGL, DirectX, Metal etc.). The every time we submit something, we keep a shadow copy of the resource we asked it to create for us and we update and delete that shadow copy when we make changes to that requested resource. We don’t actually HAVE an address for that resource because it is fully handled by the GFX Driver and not our Memory Manager. The number you see in the UI is an artificial resource ID that we use to identify that resource with and that’s linked to e.g. a Texture and the graphics memory shadow copy.

Now all of that of RAM memory, not VRAM, as on non-unified memory platforms the GPU might have to handle drawing other things than your game and would have to purge VRAM e.g. when you tab out to the OS or a different app, or it might have to swap resources in and out of VRAM as needed each frame (a performance issue that a GPU Vendor’s Profiling tool can help you analyze if you ever have to, as our profiling tools don’t have the insight into this to surface data coming from that low a level in the driver and/or GPU).

Now that shadow copy system works for allocations we explicitly asked the driver to make for us. That doesn’t keep the driver from making other allocations that our Memory Manager doesn’t even know about via such a shadow copy. That memory ends up as untracked. To analyze that you’d have to use a native platform profiler like WPA on windows, see this post.

I’d assume it’s further graphics buffers and that the growth there will taper off after a few cycles. Unless you have any plug-ins that allocate native memory without using the IUnityMemoryManager plugin Interface, which afaik FMod doesn’t. Or .net plugins or C# code using Marshall.AllocHGlobal