Table of contents
brief description
In the project where the mobile App is mixed with Unity, Unity’s package volume increment has always been a hurdle that has been strictly controlled. If the package volume increment is too large, it is estimated that the boss will not give Unity directly, so the package volume of Unity’s mobile terminal is optimized. Particularly important. Since the optimization of the Unity part in hybrid development is similar to the optimization method of the Unity independent app, here we take the Android independent app project as an example to practice a wave of package size optimization.
before optimization
I did not do any optimization and directly typed an Apk in Unity. You can use tools such as Android Studio to view the size and specific composition of the Apk for our analysis. You can see that the size of this Apk is 107.9MB. Let's take a look at its composition
It can be seen that the assets directory is the largest, followed by the lib directory, and the dex related files only occupy a small part. Let's first look at what these three parts represent:
-
assets directory: Let's first look at what the assets directory contains.
The TestData and AssetsBundles directories are subdirectories placed in the StreamingAssets directory in my project. They contain resources, which seem to be put here intact. And what is this bin directory? Click in and
you can see that it contains a lot of dll files, which are put here intact. In addition, it also contains some Resources and other referenced resources, which are not shown in the figure. The assest directory probably contains the above content -
lib directory: Let's look at the lib directory again, you can see the armeabi-v7a folder on the right, but there is no arm64 folder. You
can see that it contains various so libraries used -
classes.dex file: This is mainly java code, which accounts for a small proportion and can be ignored
Optimizing
assets directory
We first start to optimize the size of the assets directory. From the above analysis, we know that the resources in our StreamingAssets directory, the resources in the Resources directory and other referenced resources are placed in this directory, so we first optimize this resource.
The resource ab package is dynamically delivered
We change the relevant resources to dynamic loading, all of them are packaged as ab packages, put them on the CDN, and then load them at runtime. Let's use the Apk size comparison tool that comes with Android Studio to see the effect:
It can be seen that the Apk is only 60.4MB, which is reduced by 47.6M. Almost all of them are concentrated in the assets directory, and a very small part is reduced in the META-INF directory. In fact, the biggest optimization part of package size optimization for most projects is resource optimization, so almost all mobile projects will use the dynamic distribution of ab packages to optimize the package size of resources.
Resource size optimization
If there are still some resources that need to be directly embedded in the Apk, the resources can also be compressed. The size of the resources is mainly the model and the texture. The model can be optimized by reducing the surface and replacing the low model, and the texture can also be optimized by various means. , the easiest way is to control the resolution of each texture and compress the texture in Unity, as well as the combined atlas of textures. Although most of our resources use the dynamic distribution method of ab package, the resources in the ab package can also be optimized first and then packaged into ab package to reduce the size of ab package and enhance runtime performance. In the current test project, the resources are downloaded through the ab package, so this part does not reduce the package size, but it will become very useful for those projects that do not use the ab package to dynamically download
dll size optimization
At present, a lot of dlls have been generated, which occupy a lot of packages in assets, so let's continue to optimize them. This is actually because the old mono compilation method will compile C# code into an intermediate language, using the default medium optimization level, the generated binary code is relatively large, and also contains some cross-platform compatibility code, resulting in a large dll generated . Here we use the latest IL2CPP compilation method instead of mono compilation. The IL2CPP compiler will perform higher-level optimization to generate more compact and efficient native machine code for C#, so no additional cross-platform adaptation logic is required, which can reduce The size of the small packet, the following is the size we replaced with IL2CPP (compared with before optimization):
It can be seen that there is a large decrease in the assets directory, but the lib has increased significantly, and finally increased by 12.6MB to 72.9M, which obviously does not meet expectations. Why is this? In fact, it is because when we packaged IL2CPP, we chose to package the ARMv7 and ARM64 cpu architecture packages, but in the current mobile phone market, in general, we can choose one, we only choose ARM64, and then package again:
As you can see, the size has dropped from 72.9MB to 45.1MB. Let's take a look at the comparison with the mono method:
The assets directory is greatly reduced, the lib directory is increased, and the total package volume is reduced by -15.2MB (it should be noted that the size of the APK is compressed data, and the size of the directory inside is the data before compression)
Scene model dynamic download and load
We did some basic ab package loading before, but what we did at that time was only related to some resources that needed to be downloaded dynamically, and did not include the scene resources placed in the scene. Now we use ab package for all scene resources The way to download and load dynamically, verify the size again:
It can be seen that the assets directory has been reduced again, and the total package size has dropped from 45.1MB to 36.3MB. There is no detailed inspection of all the resources in the project. If they are all found out and disposed of, it can be smaller here, but due to the remaining After the resource is compressed into the apk, the size ratio is too small, so it will not be dealt with here
Optimize the size of the assets directory
Let's take a look at the size of each part in the compressed apk package after the above steps are optimized:
As you can see, the assets directory has only 5.9MB left. The lib directory still accounts for a large proportion.
lib directory
Optimize target architecture
In fact, this has been optimized before. We removed ARMv7 and only kept ARM64, which has already optimized half the size.
clipping code
In Unity's Player Settings, select "Player Settings", then in the "Optimization" section under "Other Settings", check "Strip Engine Code". This will remove unused engine code, reducing the size of the .so file. Note that this may cause unavailability of some functionality, so be sure to test the functional integrity of your application before using this option. In my test project, I opened it to the maximum clipping range, and then some problems appeared. After solving it, the apk size was reduced again: this time it was reduced to
29MB, and the lib directory and even the assets directory were also reduced.
Optimize code and references
Sometimes our code will refer to many third-party dlls. We need to know whether we must refer to these dlls. Too many dlls will definitely increase the size. To view the referenced dlls, after compiling the Apk in the Unity Editor, click Three dots in the upper right corner of the Unity Editor Console console, then select Open Editor Log, and find something similar to the following:
In this way, we can view all the dlls we reference, and then deal with them according to the actual situation. The test project will not be processed here, because this part will take a lot of time, and we need to pay attention to whether new problems will be introduced. If there are not many references, Optimization efforts are not great. In addition, we have to optimize the code we write ourselves, and try not to write invalid code.
Other optimization items
Shader optimization
We have just opened the Editor Log. In fact, the proportion of each part is displayed below. Although it is not very comprehensive, we can also get some information from it:
It can be seen that our resource part is basically not occupied, but we can see that Shaders still have some occupation, we continue to process, these shaders are actually introduced only after setting always include shaders in the project, sometimes setting But I forgot to remove it, and I can’t use it, and it will also take up memory. Let’s make some deletions according to the actual situation. I’ll make some deletions here. The uncompressed assets directory has been reduced by about 2MB, but it’s almost negligible after compression. Here we subsidize the pictures. The Shader in the project is very complicated and needs attention Here's the optimization
Release mode
We have actually been using the debug mode before, let’s turn on the release mode, and then select Use R8 to compile again to see the effect:
It can be seen that the optimization is very strong, but it will increase the compilation time and cannot be debugged, so the debug mode is still used during development, and remember to change to the Release mode when publishing.
compile options
When we package, we can choose some compression configurations. For example, in the Build window, we can change to the following two configurations:
We do packing verification again, and it ends up being the following size:
Optimized
Finally, we summarize the optimization of the above steps:
initial size | Dynamic delivery of some resource ab packages | IL2CPP (only ARM64 is reserved) | All resources are packaged in ab package | clipping code | Release mode | Compile compression options |
---|---|---|---|---|---|---|
107.9MB | 60.4MB | 45.1MB | 36.3MB | 29MB | 19.1MB | 17.4MB |
So far, we have basically optimized from 107.9MB to 17.4MB, reducing the package size by more than 80%. If you pursue the limit, there is still room for further optimization, but it is not much different from this, but the workload will increase significantly. Generally, according to the above configurations, it can already meet the needs of most projects now. And if it is developed in combination with the mobile terminal, it will also use some optimization solutions on the mobile terminal, which will further reduce the size.