Unity: Build for Android or “size matters”

In some cases, it is necessary to work on reducing the assembly size for Android . For example, installing heavyweight APKs for mobile Internet users can cost a pretty penny. Exceeding the size of the APK of 50 MB on Google Play translates into additional difficulties during the upgrade.



We developed a 2D game for Android on Unity , which is replete with pictures (most with transparency areas) and various sounds, and faced with the problem of the size of the APK. Looking ahead, I’ll say that solving it and reducing the weight by 1.5 times, we got 1.5 times more downloads. It makes you think, isn't it?

Trying to overcome the problem of heavyweight applications, we turned to wonderful documentationfrom Unity. It turned out that there this topic is discussed only in passing. Mentioned exactly which aspects affect the assembly size and how to influence these aspects to make the APK smaller, and also gives a little specificity about the settings for importing images.

We practically did not find other useful information on this issue on the Internet. Therefore, we conducted a small study, the results of which we hasten to share with you.

So, according to the documentation, the assembly size is affected by :
  1. Asset size (images and sounds);
  2. Meshes and animation clips;
  3. The size of the included dll.

We did not work with meshes and imported animation clips, so we will start with assets.


IMAGES


Clarify about the images. In our game, the principle of pixel-perfect is respected . All images without an alpha channel have a smooth gradient . The rest of the images are transparent, and the opaque areas also have a smooth gradient.

Let us analyze how the PNG and JPG images contribute to the size of the ARC .

PNG images


For PNG, this contribution depends on two “variables”:
  1. The size of the image on the file system;
  2. Import settings.

We have kept the 3 images in Photoshop settings: Compression-> Smallest / for Slow, Intrelaced: No . The 295KB PNG image took up 236KB of space in the assembly. Picture 612 Kbytes took 480 Kbytes. The 21.2 KB image took 23 KB (of course, with the same import settings). Propositionality is obvious.

Next, we saved the first picture in Photoshop with the settings: Compression-> None / Fast, Intrelaced: Yes . Got a file with a size of 9000 Kbytes, but he added the same 236 Kbytes to the assembly.

This confirms the words from the documentation that Unity will transcode all assets into the internal format.. Obviously, it roughly corresponds to the PNG format saved in Photoshop with the settings: Compression-> Smallest / Slow, Intrelaced: No. And Unity transcodes all PNGs to this format, regardless of the initial file format.

JPG Pictures


The experiments clearly showed that JPG images contribute to the assembly size in proportion to their size . It is not yet clear how Unity behaves in case the asset is in JPG format. We saved the same (first) picture in JPG and got a very small file on the file system (75 Kbytes). However, in the assembly, it took an exorbitant 767 KB (*).

We conducted an experiment on a large number of different pictures, here I give only a small part of the research. In other experiments, on the contrary, we were able to reduce the total assembly size by converting all the files from PNG to JPG.
The reasons for this phenomenon have not yet been identified.
Most likely, the internal Unity format again takes place, however, the exact principles of the interaction of the witching Unity mechanism with JPG assets have not yet been clarified.

Another way to work with JPG will be described below.

conclusions
  1. Apparently, Unity takes into account both the format in which the image is saved and the characteristics of the image and performs compression according to some internal principles;
  2. One principle is absolutely clear: images in the same format contribute to the assembly size, which is directly proportional (but NOT EQUAL) to its size on the file system .

Import settings affect the assembly size exactly as described in the dock (the better the picture, the greater its contribution to the assembly size). There are no hidden features revealed here. (No experiments have been conducted with other image formats yet.)

SOUNDS


For sounds, two import settings matter: Audio Format and ForceToMono .

Files in the WAV format take up more space in the assembly than files in the MP3 format (the contribution to the assembly size is approximately equal to the file size). A stereo WAV file will take up less space if you set ForceToMono = true . Exactly the same effect can be achieved if you convert the file to “mono” even before importing (then ForceToMono will not be available in the inspector).

However, if you set the import setting AudioFormat = Compressed for the WAV file , then in the assembly it will take up as much space as the corresponding MP3 file of the highest quality (Audacity: variable bitrate, 220-260 kbps). That is, Unity independently encodes the sound into MP3 format.

For files in the same format, the principle of a directly proportional contribution to the assembly size applies.

The remaining import settings do not affect the assembly size. They affect the amount of space occupied by sound in RAM.

A NOW ON SPECIFIC STEPS TO OUR GOAL


  1. If possible, reduce the size and quality of the source graphics files .
    (1-a) Cropping transparency areas.
    Our game used a lot of pictures with impressive transparency areas around the image. Transparency areas increase file size by only a few percent and do not really affect the size of the assembly (although cropping 102x rather big pictures saved us 2 MB). But areas of transparency increase the use of RAM (because there the pictures are presented in BMP).

    Thus, the advice: to reduce the load on RAM
    * avoid large areas of transparency in the images;
    * Do not form atlases with large areas of transparency, especially in NGUI.

    (But we are distracted from the main topic.)

  2. For images that do not have transparency and are displayed in the highest quality, you need to set Advanced-> RGB24 in the import settings . RGBA32 for them does not make sense, but leaving Automatic Truecolor is not recommended, because (as experience has shown), it can be perceived by the system as RGBA32. And this is completely redundant in the absence of areas of transparency (adds weight to the assembly and increases the use of RAM).
  3. Reduce image quality in the import settings according to the scheme: 32 bit -> 24 bit -> 16 bit, making sure that the image quality level remains within the acceptable range.
  4. Limit maxTextureSize for images for which this is possible while maintaining acceptable quality.
  5. Carefully manually remove unused assets in the Resources folders before the build process. Remember that for assets in the Resources folders, Unity does NOT automatically delete them, even if they are not assigned in the Inspector.
  6. For JPG images : change the file extension to bytes and it will turn into TextAsset. Then use the Texture2D.LoadImage () function to load the image. It should be remembered that this function loads the processor and may not be suitable for large pictures that need to be loaded very quickly. However, this method often helps impressively ease assembly.
  7. Reduce the size of sound files to the smallest possible size (taking into account quality requirements). Whenever possible use MP3, but not WAV. But if you need MP3s of the highest quality, you can also use the WAV file with the import settings AudioFormat = Compressed (Unity recodes on its own). If possible, use Mono instead of Stereo. For WAV files - set the import setting ForceToMono = true

After completing each item, it is advisable to check the effect obtained. Because the behavior of Unity still has some magic.

A few words about dll


The document lists the dlls that are necessarily included in the assembly and calls for minimizing the number of additional dlls (especially heavy ones). In particular, if possible, do not use System.dll (adds 2 MB to the APK). However, even if we avoid references to methods from this library, System.dll will still (as of Unity 4.5.5) be included in the assembly , since it is pulled by the mandatory Mono.Security.dll. Therefore, it turns out that the official Unity documentation in this place is not entirely relevant .

But the use of other (optional) dlls should be avoided in the name of reducing assembly size.

That's all for today. Thanks for attention!

(Please consider this material as more or less systematic results of the study, and not as a universal guide to action. I will be very happy for comments, observations, constructive criticism, objections, suggestions, additions. And, of course, I will be incredibly glad to know what methods are used by colleagues from other companies to resolve the issue under discussion.)

Also popular now: