How we saved ~300Mb of memory in an Unity-based project

We disabled texture atlases.

So, a company I’m currently with, is mostly a C++ shop. However, we have this one Unity-based project, which was developed by now-gone programmer. It’s quite FUBAR, even though it’s been released to stores about six months ago. Now, our higher-ups decided to try to salvage it and maybe extract a bit of profit from it, so we added English localization and tried our best to make it crash less.

After starting to work on it (while learning Unity on the fly, because only one man in our team had any major experience with it), we soon discovered that the reason for those crashes was memory. A simple Match-3 game was taking up about 400Mb! Many Android phones did not give us that much, even those that have 1Gb RAM (Sony, I’m looking at you!).

The whole project was created in a single Unity scene, so all resources were loaded at startup and kept in memory forever. First thing we did, we separated different game screens into prefabs, and started loading/unloading them as needed. This move lowered memory consumption to around 350Mb, which seemed like a smallish victory, until we discovered that we need to call Resources.UnloadUnusedAssets after unloading old screen to REALLY free up memory. That brought us down to about 300Mb on the heaviest screens. Which still wasn’t good enough.

This is where I came in. For a few days, I tinkered about with textures, moving them from altas to altas (before, they were assigned more or less randomly), changing compression settings etc. I won a few small gains, but the main problem remained: unless I was committed to sorting all textures properly, so any screen would only load those it needs, I was still seeing too much memory being eaten by large atlases. For example, where the game needed to draw a five-piece GUI, it would pull up a couple of 2048×2048 atlases, because those pieces were also used in other separate places.

So, I disabled atlas generation altogether. Memory consumption dropped to ~150Mb on average screen and ~200Mb on the heaviest one! And there was no noticeable loss of performance, because this game did not really NEED atlases. It makes too small number of draw calls to benefit from batching them.

In the end, I re-enabled atlas generation, but only put game tokens in it. It did not provide any performance boost, but I felt that it is better to draw all of them in one batch, since there are a lot of them on screen at the same time during the level, unlike GUI pieces or other graphics in this game.

So, morale of this tale: when putting things in atlases, consider what you are doing carefully. Do you REALLY need it? No, unless you’re drawing a lot of stuff at the same time! And an atlas will always consume more memory than its constituent textures.

I'm a video games programmer. I have worked in game industry since 2008 on MMOs and mobile games, but now I work for Owlcat Games on great old-school RPGs. In my free time, I like to play rock'n'roll on my guitar and travel.

One thought on “How we saved ~300Mb of memory in an Unity-based project

Leave a Reply

Your email address will not be published.