Optimizing build size and performance with proper sprite setup

Bruno Mikoski
6 min readMay 18, 2020

--

For game developers and especially mobile developers, both performance and binary size is a constant concern and is something that we need to keep in check constantly.
Performance, because we want to have a smooth frame rate and one that does not burn your fingers while playing it. One of the biggest causes for heat on mobile devices is: Draw Calls.
Binary size, because we have devices with extremely high-resolution but we still have to worry about mobile data download on the stores. Did you know that For every 6 MB increase to an APK’s size, we see a decrease in the install conversion rate of 1%?

So today I want to talk about how we can tackle both of these issues by just taking proper care of our sprites, it doesn’t matter if it’s UI for a 3D game or a full 2D game.

The setup

To be able to demonstrate this properly I’ll be using the Lost Crypt — 2D Sample Project from the asset store:

I’ll just import the package into an empty Unity project and make a release Android build to check where we stand:

Initial Benchmarks

APK Size: 102.868 KB

The Optimization Process

I’ll be using a tool that I’ve developed to help with this process, the Sprite Auditor. You can get it here (https://github.com/badawe/SpriteAuditor) You can follow these steps without it, but this tool makes things a lot easier.

1- Setup the environment

The first thing you need to do is define what is the target resolution, in this case I will go for 1920x1080. This will give us a benchmark of what is the size of things in proportion to the resolution.

This is important for the Sprite Auditor tool been able to recognize the size of the images in use.

2- Capturing the Data

In this case, I’ll be using the Sprite Auditor to capture the data that we need. If you are doing it manually then it’s just a lot more steps to see what sprites you are using in each scene.

So let’s open the Sprite Auditor by the menu Tools/Sprite Auditor and dock it somewhere.
You must be aware that the performance of the game while running with the Sprite Auditor attached is going to suffer since it’s looking for all know possible sprite usages.

I’ll leave all the default settings and just press play while keeping the sprite auditor window docked somewhere. Since this is a pretty small demo, I’ll just manually go to each individual scene and screen. Ideally you can attach this to your unit test, to make sure you are getting everything that your project uses.

And these are the initial results:

3- Tweaking

There’s a lot of things that we can see here. First is that there’s no Atlas, so all the sprites are Single Sprites or Multiple Sprites. Most of the time when we are talking about binary size, making use of an Atlas is a good approach since it can pack textures better. Let’s start by checking those sprite sizes. For doing that there’s a filter on the right where you can Filter only Sprites that have been used smaller than the Sprite Rect:

After checking with this filter, we can start seeing some of the optimizations that we can make. For instance: Sprite_Soft_1

You can use the Select button to see where this sprite has been found, but what we are looking for here, is the warning on the bottom. This warning means that for our target resolution this Sprite has been used 88,69% smaller than our Imported Size. We can make it smaller and for single sprites you can use the Fix Texture Size button, that tries to find the best resolution for this sprite.

So now the maximum size of the sprite has been changed to 256x256, and this is a really interesting case because probably we could get away with 128x128 since the maximum usage size is 135! But for the sake of finishing this let’s use the “appropriated size” for now, so let’s do this for all the sprites that have the Warning and we can size that they have been scaled down on the game and see where we end.

Let’s make a new build and see the results.

Reducing Sprite Size Results

APK Size: 86 112 KB not much, but we will get there ;)

3- Implementing Atlas

The next step now is creating a Sprite Atlas to accommodate sprites better.

Since the whole demo is only one scene, this is quite easy. But since optimizing an Atlas is almost an art in itself, the way I normally do it is like this:

Imagine that you have a simple game with a Main Menu and Gameplay scenes. The idea is to make sure everything that belongs to the Main Menu only, goes into the Main Menu Atlas and everything that belongs to the Gameplay Only goes to another Gameplay Atlas. And normally I have a Generic Atlas for things that should coexist between those two scenes like Icons, Popups, Buttons and this type of stuff. But let’s get back on track.

Let’s create a new atlas on the project and call it GameplayAtlas. Now using the Sprite Auditor we can quickly move all the used references to our brand new atlas.

This is super helpful but thinking on the long term, that having a proper folder structure to manage your atlases and sprite references it’s also super handy.

Reducing Sprite Sizes + Sprite Atlas result:

APK Size: 55 503KB!!!

That almost half of where we started!

Final Tips

  • Consider using a folder structure where it’s clear for both art and tech where things should go, example
You can directly reference the Source Folder inside the GameplayAtlas packable, so any new image that gets added to the source folder will be automatically added to the atlas as well.
  • Even if you have a Texture 2D with multiple sprites inside, you can add individual sprites from this Texture directly into another Atlas
  • When thinking about Draw Calls and performance optimization it’s important to make sure you have atlases that can be batched together on the same page. For instance: a Unique atlas for the Character.
  • Avoid using only one sprite from an entire atlas on a different scene, consider creating a new Atlas for it.
  • Keep your Pixel Per Unity consistent and tweak everything else to make sure things are on the appropriate size.
  • It’s not a problem that all your assets in your game are in 4K, since we can always tweak the max texture size to optimize it down when necessary, but we can’t scale up!
  • Keep your art resolution consistent. Make sure you are in sync with your art team, to make sure everyone is working and exporting assets on the same resolution.
  • Every new page of your atlas will result in a new Draw Call, so performance-wise makes sense to combine objects that “belong” together

That’s it for today, I hope this is helpful :)

Shout out to my friends @Chrusb and @sezdev who helped with the revision.

Follow me on Twitter: twitter.com/brunomikoski
Check my other assets on Github: https://github.com/badawe

--

--