March 16 2020
By Rubén Torres Bonet
March 16, 2020
I have a question for you regarding Unity memory management; when exactly is Unity releasing the memory your game assets are taking?
Most game developers wrongly assume it’s released when you stop using them (whatever using means).
But… This assumption is wrong.
Let’s find out why.
In this post, I’ll share with you:
There’s a reason this topic is relevant.
Here’s what I see in most profiles: an increasing amount of used RAM and a confused developer asking me why.
“That must be wrong, I’m destroying my game object instances“, they tell me.
And here’s what I usually answer: “sorry, destroying instances won’t necessarily get your memory back“.
If you’re aware of this fact, this issue will rarely be a concern.
But if you’re not, then you might run into confusion and/or trouble.
Let’s see why.
Here’s a typical case:
And the last one: you call Addressables.Release(myInstance) on an addressable asset. You’re furious to see that nothing changed in your memory layout.
“What the f*** is going on here?”, you curse aloud.
These all are examples of wrong assumptions most game developers make regarding Unity memory management and asset unloading.
And these assumptions might have somewhat nasty consequences.
If you believe memory is released when it is NOT, then you might run into trouble at some point.
You’ll think you have more free memory than you actually have.
→ This won’t endanger your game often, as a good operating system will kindly remind Unity to clean its shit when it becomes too greedy. But some OS won’t be that forgiving when it comes to memory (Oculus Quest comes to mind).
However, your mental sanity is at risk.
If you ever played Arkham Horror, or Eldritch Horror for the matter, you’ll know better than to play with sanity points.
→ Here’s the second problem: profiling your game won’t be accurate anymore because the numbers you see won’t match what you expect.
This will lead to questions such as “where are these extra 200MB coming from?” or “why is this still in memory even if I destroyed all references to it?“. Even worse, you could end up asking yourself why are you in gamedev after all.
Okay, calm down.
We want both our gameplay and our profiling experiences to be silk smooth, right?
We don’t want to hear the iron-like fist of our boss striking your desk asking about those kickstarter users complaining about crashes.
All good. I’ll help you understand when exactly Unity unloads your assets and how to help it do it sooner.
I’ll split the explanation in two sections:
Basically, Unity wants it safe for the game developers. And so it adds protection.
Unity is over-protective of memory and therefore under-performing.
I don’t say this is wrong, as this saves you from taking aspirin. But they could be more transparent with memory management so everybody is aware of what’s going.
If you’re not using addressables but the traditional memory management flow, Unity follows a specific memory release pattern: Unity releases your assets’ memory during the cleaning process and only if your asset meets the cleaning requirements.
This is when the memory cleaning process takes place:
And this is the basic requirement for your asset to be freed: your asset must NOT have any live reference pointing to it at the moment of cleaning.
These asset references exist in components that live within a game object that is alive in your current scene hierarchies.
To sum up: it’s hard to have efficient control over memory when using the traditional memory management workflow.
Luckily, you can always upgrade to Addressables to have finer control over memory as we’re about to see.
Unity Addressables is a system that significantly upgrades the way you work with references.
The Addressables API lets you decide when to load and unload your assets even if you keep references to them. The traditional workflow doesn’t give you this privilege.
You do these operations by calling the LoadAssetAsync and Release methods on specific addressable asset references.
Addressables makes memory management much more predictable for the professional game developer.
However, this is not without misconceptions.
You see, calling Release is not guaranteed to free your asset’s memory.
Let me explain how this works.
Now, the meaning of destroying is different depending on the type of addressable asset you’re talking about.
If we’re talking about an addressable asset, then destroying it won’t actually do much, other than messing with the internal cache of the addressables system. This means: releasing an addressable asset won’t release its memory by itself.
But here’s the thing: your addressable assets live within an asset bundle. And asset bundles also have their own reference count.
If the system detects that an asset bundle containing addressable assets has no live dependencies (e.g. addressable assets), then its reference count becomes 0 and the asset bundle is destroyed.
And that’s the key: destroying an asset bundle is the operation that will truly free the memory of the addressable assets it contains.
Once you know this, it’s very easy to be mindful about managing your memory.
You’ll see things click. You’ll understand why it’s not a good idea to create huge addressable groups — i.e. asset bundles.
If you’re suffering from this problem, you have to easy ways of relieving memory pressure:
Now you have knowledge
Now you have control
Now you have work
As you can see, you barely have control over your own memory if you’re still using the default Unity memory management system.
To avoid all this trouble and to make sure your game stays on top from development to release, it is important that you switch to the modern era of addressable assets.
The best way to start is to check out my Unity addressables tutorial. There, you’ll learn why your game might need addressables and how to get started quickly.
I hope this post helps you at some point during your career.