Gamasutra is part of the Informa Tech Division of Informa PLC

This site is operated by a business or businesses owned by Informa PLC and all copyright resides with them. Informa PLC's registered office is 5 Howick Place, London SW1P 1WG. Registered in England and Wales. Number 8860726.


Gamasutra: The Art & Business of Making Gamesspacer
arrowPress Releases







If you enjoy reading this site, you might also want to check out these UBM Tech sites:


 

How to Rescue Memory on Disabled GameObjects Without Destroying Them

by Ruben Torres Bonet on 01/28/20 10:54:00 am   Expert Blogs   Featured Blogs

The following blog post, unless otherwise noted, was written by a member of Gamasutra’s community.
The thoughts and opinions expressed are those of the writer and not Gamasutra or its parent company.

 

[Check the original post at Unity Save Memory Within OnDisable]

One of my students, Ryan, asked me last week how he could rescue the memory Unity was stealing from his game because of disabled game objects. Luckily, he was using Addressables, so I prepared an experiment...

In this post you'll learn:

  • When is it ok to have deactivated GameObject's
  • Why disabled GameObjects pose a threat to memory
  • How to get your memory back without destroying them


Ready?

With Unity, there are many reasons you might want to deactivate entire GameObject hierarchies in your scenes...

  • Maybe you don't want specific elements to be visible or executing yet.
  • Or maybe you're doing object pooling.

In any case, deactivating a game object effectively disables invoking the Update behavior.

And that's great, because deactivating a GameObject will save you precious CPU cycles.

However, it's not all perfect...

There's one thing we're not saving on when disabling objects: memory.

You see, keeping a direct reference to your assets will keep them loaded in memory. It doesn't really matter if they're invisible, disabled or whatever. Direct reference = memory greed.

But today I have a trick up my sleeve for you.

I'll show you how to recover the memory your disabled game objects are feeding on.

No worries, we'll make sure they get their memory back once they awake. We're not that selfish after all.

Quick Navigation (redirects to new tab)​

Chapter 1: A Typical Scenario: Wasting Memory

Chapter 2: An Alternative Scenario: Saving Memory

Chapter 3: Conclusion & Comparison

CHAPTER 1: 
A Typical Scenario: Wasting Memory

In this chapter, I'll show you a simple Unity scene that contains a few referenced assets.

You'll see how they refuse to exit memory when we deactivate their objects.

As simple as it is, this represents a vast amount of examples I've seen across a multitude of projects.

So my guess is that you suffer from this in your project.

To make a case for the post, I created a simple Unity scene with the following scene hierarchy:

  • Pause Canvas
    • Image0 → Sprite0
    • Image1 → Sprite1
    • Image2 → Sprite2
  • SoldierCharacter → Static Mesh + 4 Materials

In this case, it doesn't always make sense to keep these objects active...

  • If you're not paused, there's no need to keep their sprites in memory.
  • If the soldier is pooled and waiting for its turn to spawn, it's better to keep it deactivated.

You might say: If I want the memory, I can just destroy it.

And you'd be right. You could destroy them to save memory.

However, some game architectures rely on persisting state within your objects. You might want to store the last parameters the pause menu had. Or you might want to save the customization parameters of that soldier that we will spawn after crossing that door.

No matter what, there'll be circumstances where you'll have deactivated objects for certain period. And it might be wise to save memory on those until the moment of the activation occurs.

Here's how the setup scene looks like (don't judge my art style, I'm a programmer)

Saving Memory OnDisable: Setup Scene

Saving Memory OnDisable: Setup Scene

As you can see in the GIF below, deactivating the whole hierarchy won't release a single bit of memory (actually I'm not sad about it, as this keeps me employed).

Unity Default Behavior: Memory GreedUnity Default Behavior: Memory Greed

And that's the problem we are about to tackle in the next chapter.

CHAPTER 2: 
An Alternative Scenario: Saving Memory

In the previous chapter, we've seen how deactivating game objects help reduce CPU usage. But it doesn't really help us reducing our memory usage.

In our example, we still pay memory for the following asset types:

  • Textures
  • Meshes
  • Sprites

In this chapter, we'll get rid of this memory cost in a sneaky way.

Alright...

We're going to use Addressables.

And the trick is going to be a relatively simple script.

From a high-level perspective, this is what we're going to do:

  1. We're creating a simple script that holds an indirect reference to the asset our original component is using. This could be an indirect reference to a sprite being used in a UI Image, or a material in a MeshRenderer or a mesh in a MeshFilter.
  2. We then remove the direct reference from the original component (Image, MeshFilter, MeshRenderer).
  3. The script will load the asset during OnEnable and assign it to the correct field.
  4. When we disable the object in OnDisable, we unload the content.

This approach simply works for a simple reason...

When someone decides your content must be visible, your game object will be activated. This, in turn, will call our script's OnEnable function where we will load the relevant asset.

The same applies in the other direction. When we're done with an object, we either disable or destroy it. But whatever function gets called is not relevant for us, as Unity calls OnDisable for us and there we'll get rid of that memory section.

In my example, I implemented this simple mechanism for 3 components:

  • MeshFilter: indirect reference to a Mesh
  • MeshRenderer: indirect references to Materials (and therefore textures)
  • UI Image: indirect reference to a Sprite

And you are just about to see the results of this script in the profiler...

Unity Addressables: OnDisable Memory Gain

Unity Addressables: OnDisable Memory Gain

Yeah, as I said, that just works.

And the good news is that you can extend this to other components and asset types such as SkinnedMeshRenderer and the like.

CHAPTER 3: 
Unity: Save Memory - Conclusion & Comparison

So far, we've seen how Unity's default behavior doesn't encourage efficient memory usage patterns.

But we also saw a way to fight the battle and reclaim our memory.

A question that remains unanswered is... is this fight worth the price?

As you might have noticed, this solution isn't free of side-effects.

To use it, you must be willing to pay a price: latency.

Indeed, loading an asset asynchronously will often take several frames. Depending on the frame-rate you're targeting, it might be unnoticeable but there's always the chance you can spot the small delay.

However, often enough you'll just need the memory savings. This is especially true if you're targeting older Android devices.

And honestly, it's not always about needing. Every MB you save on memory will reduce the chances of crashes.

You never know what the user is running at any given time, so the less memory you use, the better off the reviews of your game will be.

To quickly recap what we achieved with this Addressables-based tool, here's what we got:

Unity Addressables: OnDisable ComparisonUnity Addressables: OnDisable Comparison

That's a respectable saving on this particular scene, I must say. Of course, this will immensely vary depending on your use case.

My suggestion?

Try it out in your game and let me know your thoughts.

This tool works by:

  1. Having a basic Addressables setup (check my tutorial on Unity addressables)
  2. Attaching and setting up Mesh_ManageMemoryLifecycle to your static mesh or Image_ManageMemoryLifecycle to your UI image.

Remember: the sprites, meshes and materials you want to target must be addressables-activated.

Here's how the components look like:

OnDisable: Memory Gains for Meshes

OnDisable: Memory Gains for Meshes

OnDisable: Memory Gains for UI Images

OnDisable: Memory Gains for UI Images

Neat, isn't it?

Grab the tool and the unity sample project to start getting memory gains today


Related Jobs

Scanline VFX
Scanline VFX — Los Angeles, California, United States
[05.26.20]

Unreal Technical Director
Square Enix Co., Ltd.
Square Enix Co., Ltd. — Tokyo, Japan
[05.26.20]

Experienced Game Developer
Moon Studios
Moon Studios — Remote, California, United States
[05.26.20]

Senior Character TD
innogames
innogames — Hamburg, Germany
[05.26.20]

(Senior) Java Developer





Loading Comments

loader image