Unity Memory Management in 2D

24 July 2015

While we're new to mobile development, we've learned quite a bit already about how to improve memory usage on devices.

This is a MAJOR issue in the mobile arena as many older devices have very limited available memory. Exceed the memory available on the device or ignore a memory leak and you can count on your game Derpppping out hard. Memory derps can present themselves in the form of crashes, hangs, failure to start, failure to render textures, and other general badness.
Previously, when developing for Flash, we could rely more heavily on the player using a more powerful laptop or PC. So while memory was an important consideration, it was slightly less of an issue. Now, it's safe to say that memory management is enemy #1 in mobile game dev.

Consider the Following:

While BioBeasts is a relatively small project, we already have tons of textures and assets. Here are some enemies already in game:

Because we want our graphics to look great on many devices (even the new ones with crazy resolutions) we create these assets at a nice high resolution... this comes with a file size cost and of course a memory cost. Too many big textures in your game and things go Keeeeersplodeeee.

Here are some techniques we've found to help address the memory issue:

Selective Loading - Don't load 100% of everything all the time. This is a recipe for disaster. BioBeasts loads and unloads assets as they are needed. Be careful though, because loading assets comes with a performance hitch at the moment you call Load. To overcome this issue, you'll want to create designated load / unload points where game play won't be interrupted or diminished by annoying loading fps spikes. You can use these moments to to bring assets in and clean them up when no longer referenced by your game. Look up Resources.Load() and Resources.UnloadUnusedAssets() for more information.

To cleanly cover our loading moments, Charfade created some metal lab doors that close over the game during loading / unloading. You'll have to wait for the full release to see the final painted version of these snazzy doors):

Pool Objects - If you are going to create 1000 of the same fireball during gameplay, don't create 1000 fireball instances. Instead create a pool of a few fireballs, and recycle them as needed. This will dramatically improve performance as you don't need to call Instantiate() a zillion times which has a very high performance cost in Unity. There are loads of Object pooling scripts online, and if you're interested, just ask, we can share more on how ours works.

Pack and Compress Sprites - While it makes sense for the art team to create assets in a logical order (each interface on its own sheet), Unity doesn't care how neat you are. In fact, Unity just cares about the number of draw calls and total memory load from how many textures you use at the same time. If you can reduce your texture sizes and number, you will improve memory usage. To help condense your sprites, try Unity's Sprite Packer: You can assign each sprite a packing tag, and compress similar assets together into condensed sheets. Here's an example where map assets for the same map are packed into a single sheet:

Use the Profiler - With a device connected, select the memory section, switch the view to 'Detailed' and click 'Take Snapshot.' This will give you a breakdown of the memory usage in game at that moment in time. If you open the Texture2D section you'll see your largest memory hogs.

Have a question about memory management in Unity? Share your thoughts or tricks of your own below!