How to make a minimum size build in Unity?

Happy New Year everyone! My name is Grigory Dyadichenko and I am a technical producer. Build size. Today I would like to talk about it and draw up a kind of checklist that is useful to go through before laying out the project. If you are interested in how you can reduce the weight of the assembly with Unity tools – welcome to the cut!

One of the big challenges in development that everyone faces all the time is optimizing build weights. On the web, it is better to have a minimum weight of the application. There is a restriction in mobile stores that the build should weigh no more than 100 mb for downloading over a mobile network on IOS and 150 mb for Android in the case of an app bundle. It seems that only the developers of Call Of Duty do not care about the size of the assembly, but let it be on their conscience. Before release, it is important to go through the assets in your project and trim what and where you can.

What does the application consist of?

Before you start optimizing, you need to understand what we can optimize and what should be optimized. The application consists of:

  1. Textures

  2. 3d models

  3. Animations

  4. Sounds

  5. Shaders

  6. The code

  7. Engine code

We will go from simple optimizations to complex ones. From more effective and top-priority, to those that need to be done at the “very last moment”. Let’s start with textures.

Texture Optimization – Texture Atlases

Textures are a common pain in both 2d and 3d projects. So let’s start with them. And let’s start with the simplest concept texture atlas.

texture atlas – this is an image that collects other images in itself. In fact, a large texture is taken and through uv coordinates is divided into zones in which other textures will lie. This is the very base, but it is important to know. Texture atlases optimize both rendering and build weight.

For 2D and interfaces, Unity has the Sprite Atlas mechanism. In order for the atlases to work, you need in the settings Project Settings->Editor->Sprite Packer enable Sprite Atlas. If it is not enabled, then the generated atlases will not do anything.

To create an atlas in Unity. Need to do in the project files Create->2D->Sprite Atlas. And further into the field Objects for Packing put the desired textures (you can also put a folder).

Important: to avoid artifacts in the UI, disable the Allow Rotation and Tight Packing settings. For SpriteRenderer everything will work fine with these settings.

In the case of 3D games, atlases are usually assembled in 3D software. There are assets for combining materials and forming atlases for 3D. But this is more about rendering optimization than build weight optimization.

Texture Optimization – Compression Settings

When the atlases are configured, you can try to shake them again or shake the textures. There is no specific recipe here. Let’s say if you focus only on top mobile devices, then ASTC compression will most often work there without problems, even on android. You can choose different options for the compression itself and adjust them to find a balance between weight and artifacts. For example, let’s take a cover from one article.

With the default settings, and even we have it and NPOT (sizes are not a power of two), it weighs 2.6 mb.

Returning to the previous point. We’ll put it in a sprite atlas. Now it weighs 2.0 mb, although it has become larger. How did it happen? Previously, it was not compressed (because the texture size was not a power of two and some compression algorithms do not work in this case), but now it is with ETC2 compression. But we want to see “real compression”.

And now let’s look at two screenshots. Please note that some compression formats are not supported by devices.

Was: (2mb)

Now: (230kb)

And so we reduced the size of our texture from 2.6 mb to 230 kb. More than 10 times. Since this is a deep degree of optimization, it is important to test such things well.

Important: it doesn’t matter how much the file weighs on your disk. And then some optimize textures with external utilities. This only works if the textures go to the as-is build, say through a folder StreamingAssets. But it’s usually better to use the engine’s compression settings without thinking anything up.

Texture Optimization – Gradients

The main thing that compression can break is gradients. But gradients are a mathematical object that may not take up space at all in a project. I wrote an entire article on this topic.

In general, gradients on buttons and backgrounds are best done with shaders. It is strange to see a background in the form of a gradient in the project with large 2048×2048 sprites. Which, say, on android either comes without compression, or with ladder artifacts. It’s better to just make a shader. In terms of performance, shaders are trivial. Application weight will be lower. It will look more beautiful.

Texture Optimization – Approach to UIs

This point is not always possible. But often (especially in business applications) the entire interface can be assembled “from one circle”. Here is an example of fairly simple options.

Often the whole interface is a set of icons, 9-slice sprites and gradients. By making one border frame for the Sliced ​​display mode. Using shaders from this article + masks as gradients. You can collect most of the windows, buttons, etc. And this is more of an approach to production at the start of a project. To the requirements for artists and so on. It is very sad to see some huge window backgrounds in atlases, especially if they were easily made using a similar technique. Let’s say if you take windows more complicated, then here’s an example nicer made in the same way.

The background of the buttons is general. The popup is made up of small squares at the bottom and small sprites that make a “torn paper” effect. Large backgrounds are just needed to get the dimensions of the layout on a given sheet. It turns out a complex window consisting of an atlas 256 x 128, although the size of the window itself is 388×473 and when assembled “bluntly” – it would be two sprites of a similar size.

That is, basically atlases should have icons and similar forms for 9-slice. You can learn more about 9-slice read here.

Important: Why not use a shader for fillets and the like? As shown above, forms are very different, but this is not the only thing. When using mesh or shader generation, it will be difficult to do anti-aliasing in the general case to avoid laddering on these fillets. Therefore, it is better to use sprites and 9-slice technique.

Model optimization

With models, it is important to understand what makes up the weight of the model. We will take out the animations in a separate paragraph and see what kind of vertex parameters and what can be done with them?

Changes in the weight of the model as a whole in Unity cannot be seen (only in the editor logs in the assembly). But it can be appreciated if you look at the mesh of the model. For example, we see that the vertex in our model weighs 1 mb. Can we somehow reduce this? Yes, but there is a nuance. It is important to understand what vertex parameters are responsible for. For example, in our AR projects, we use shaders that most often do not need normals. Let’s turn them off. It’s done here.

And the weight of the vertices has decreased by half. At the same time, we have not lost anything (in the context of the project).

So, unfortunately, it is not always possible to do so. But in any case, do not forget that the model consists of vertices and triangles. Triangles are not particularly optimized, but vertices can be. And often mesh normal data is not needed on low end devices as light is baked into textures.

Immediately I would like to say about Mesh Compression without making it into a separate paragraph. This setting can also reduce the weight of the model quite significantly. But it causes artifacts and you just need to go through the models with it, see that nothing critical has broken and leave it at the right level.

Optimizing Animations – Approach to Animations

Here we will mainly talk about 3d. The most important requirement in animations in 3D models in Unity is that all animations must be inside the same model. In this regard, the same mixamo is not very convenient, since it downloads a separate fbx for each animation. Why is that bad? In this case, you are just pulling a bunch of extra models, since the engine does not understand that these are the same model. FBX are different.

Therefore, animations must be in one fbx and cut into separate clips already in Unity.

The rest is just setting the error and the animation compression mode, which is also done for each model according to the principle: “until critical artifacts appear.”

Optimization of sound, shaders, code

Here in Unity there is nothing particularly interesting in terms of settings or not such a strong influence on the weight of the build. You can still try to optimize the sound by reducing its quality in the compression settings. And for the rest, “use everything lightweight.”

Engine code optimization

But this is quite difficult and risky. This is done by disabling Built-in packages and enabling Strip Enigne Code – High. On the same android, this allows you to win about 5 MB of the total weight of the application. And it is better to include this setting at the start of the project in order to understand what exactly is broken. Since Unity will often say not “what’s the problem”, but will say “try disabling the Strip Engine Code”. It can break some functionality, break asset bundles, break a lot of other things. But you can use it.

First of all, for this it is important to understand what link.xml is, which is described in detail in the Unity manuals stripping and by Unity linker. But the very topic of how to work with this so that nothing breaks when creating bundles is a separate article.

In conclusion – checklist

Thank you for your attention! In the end, I want to collect a small list of actions that should be done before the release of a project or a new feature in order to keep the build size small. But first I want to say something that has not been said. About the main build size analysis tool. Editor log.

If you are not initially focused on the task of “build weight should be minimal” as is done, say, for promotional projects on the web or playable ads. Most often, it is enough to shake textures and 3D models. Other optimizations start when “it’s really necessary to win the last megabyte”. But first of all, you need to look at what as a whole takes up space in the assembly. According to the log, oddities and where “something is wrong” will most often be immediately visible.

So, now the checklist:

  1. View build editor log and find oddities

  2. Check that all textures are in atlases

  3. Customize atlas compression for target platforms

  4. Check there are no gradients in the assembly that can be replaced by a shader

  5. View the weight of the largest 3D models and try to change the Mesh Compassion by checking the result on the devices

  6. If some vertex parameters are not used, ask the modelers to remove them from the model and disable their import into Unity

  7. Check that there are no “duplicate models” in the project for the sake of animations

  8. Optional: Go through the sound quality settings and for the largest ones, look for a balance between quality and size

  9. Worst case: Turn on Strip Engine Code – High and fix everything that breaks (never do it right before release)

Well, that’s all. The rest is already subtle optimizations depending on the context of the project. Like the palette technique or packing multiple textures into one texture. As you can see in the article, many optimizations are not made at the last moment, but are built at the process level. So I wish everyone small builds and great success in game development! Subscribe to my telegram blogthere are many interesting things.

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *