Eight controlled Unity Android builds show how texture, audio, Korean font, and DOTween choices change APK size, with reproducible data and source code.
Most developers know that textures are heavy and uncompressed audio is bad. But ask which setting added how many megabytes to a real APK, and the answer often gets vague.
After 14 years of building and shipping Unity mobile games, I wanted measurements rather than folklore. I started with a minimal project, changed one variable at a time, built eight Android APKs, and then repeated the entire run.
The largest difference between the two runs was 8 bytes.
For per-asset measurements, I used the BuildReport parser included in the public experiment repository.
Run it yourself: The complete Unity project, build automation, both repeat-run CSVs, and every per-step raw report are public in the BuildAnalyzer GitHub repository.
The setup
- Unity
6000.3.7f1 - Android APK, not AAB
- IL2CPP, ARM64 only
- Built-in Render Pipeline
- Development Build off
- Managed Stripping Level: Medium
- Engine code stripping enabled
- One scene with one camera, one directional light, and one cube
The scene included a small reference harness so every test asset was genuinely referenced. That makes the 14.32 MiB baseline specific to this experiment, not a universal Unity minimum.
I measured the APK itself with FileInfo.Length:
var artifactBytes = new FileInfo(report.summary.outputPath).Length;
This matters because BuildReport.summary.totalSize, the sum of packed assets, and the final compressed APK size are three different metrics.
The results
Each row changes one condition from the row immediately before it.
| Step | Controlled change | APK size | Delta |
|---|---|---|---|
| 0 | Minimal experiment project | 14.32 MiB | - |
| 1 | Referenced 2048x2048 texture, Android RGBA32 | 28.12 MiB | +13.80 MiB |
| 2 | Same texture, Android ASTC 6x6 | 16.14 MiB | -11.98 MiB |
| 3 | Add referenced 30-second stereo audio, PCM | 21.19 MiB | +5.05 MiB |
| 4 | Same audio, Vorbis quality 0.5 | 16.60 MiB | -4.59 MiB |
| 5 | Add full Noto Sans KR dynamic font | 19.49 MiB | +2.89 MiB |
| 6 | Same font, app-specific subset | 16.63 MiB | -2.86 MiB |
| 7 | Add DOTween, preserved and referenced at runtime | 17.10 MiB | +0.46 MiB |
Texture: RGBA32 vs ASTC
The test texture was an opaque, deterministic 2048x2048 noise image with mipmaps disabled. Using high-entropy pixels prevented APK ZIP compression from making an uncompressed texture look artificially cheap.
| Android format | Packed texture | APK |
|---|---|---|
| RGBA32 | 16.00 MiB | 28.12 MiB |
| ASTC 6x6 | 1.78 MiB | 16.14 MiB |
ASTC reduced the texture's packed contribution by 88.84% and removed 11.98 MiB from the APK. The ASTC build was still 1.82 MiB above baseline; compression did not make the texture free.
The practical lesson is not simply "use ASTC." Pick a format and block size that your target devices support, then inspect the visual cost on real hardware. But leaving a large mobile texture as RGBA32 is an expensive default.
Audio: PCM vs Vorbis
The audio input was deterministic 30-second stereo PCM at 44.1 kHz. It contained several tones plus noise so it behaved more like real content than a silent WAV.
| Android format | Packed audio | APK |
|---|---|---|
| PCM | 5.05 MiB | 21.19 MiB |
| Vorbis, quality 0.5 | 0.46 MiB | 16.60 MiB |
Vorbis reduced the packed audio by 90.98% and removed 4.59 MiB from the APK.
That does not make Vorbis correct for every clip. Short, latency-sensitive effects and long music tracks have different runtime requirements. The important part is that import format is a measurable build-size decision, not a housekeeping detail.
Korean font: full source vs app subset
For the font test I used the same Noto Sans KR Regular dynamic font in both builds. The first build embedded the full source font. The second used a subset containing the characters required by a small example UI plus ASCII letters, digits, and punctuation.
| Font condition | Packed font | APK |
|---|---|---|
| Full Noto Sans KR | 5.94 MiB | 19.49 MiB |
| App-specific subset | 0.07 MiB | 16.63 MiB |
Subsetting reduced the packed font data by 98.88% and removed 2.86 MiB from the APK.
This is specifically a dynamic source-font comparison. A TextMeshPro static atlas has different tradeoffs, and a dynamic font may need fallback glyphs or downloadable language packs. Do not quote this percentage for every font pipeline. Do measure the character coverage your product actually ships.
DOTween: the part PackedAssets did not explain
For the final step I enabled the DOTween Free DLL for Android, preserved it through linking, and referenced it at runtime through the experiment harness.
The APK grew by 0.46 MiB. But PackedAssetInfo attributed only 192 bytes to the DLL path.
Most of the increase appeared elsewhere:
-
libil2cpp.socompressed size grew by about 0.36 MiB. -
global-metadata.datcompressed size grew by about 0.06 MiB.
This is the result that changed how I think about the analyzer. A per-asset report is necessary, but it cannot explain all code growth. A useful build analyzer needs to show at least three layers separately:
- Final artifact bytes
- Packed asset contributions
- Native and managed code or metadata changes
What surprised me
The texture was the largest single increase, but the font result was more useful. A full Korean dynamic font added 2.89 MiB to this APK; an app-specific subset recovered almost all of it.
The second surprise was the metric mismatch. In the final build:
- APK artifact: 17.10 MiB
-
BuildReport.summary.totalSize: 143.54 MiB - Packed asset sum: 5.60 MiB
None of these values is wrong. They answer different questions. Reporting one as if it were another creates a very convincing but incorrect chart.
Finally, the two full experiment runs were remarkably stable. Across 16 APK builds, each matching step differed by at most 8 bytes. That made the large deltas easy to trust.
The takeaway
Build size is not one big mistake. It is an accumulation of import formats, referenced content, font coverage, enabled code, engine modules, and packaging.
The controlled experiment produced three high-value changes:
- ASTC 6x6: -11.98 MiB versus RGBA32
- Vorbis quality 0.5: -4.59 MiB versus PCM
- App-specific Korean font subset: -2.86 MiB versus the full font
The exact numbers belong to this project and configuration. The method is the reusable part: fix the build settings, change one variable, measure the final artifact, and use BuildReport to explain what changed without mistaking it for the artifact itself.
You can clone the public experiment repository and run all eight builds from the Unity menu or command line.
Next, I will apply the same measurement loop to a real mobile project and track which changes survive contact with production assets.
I'm a Unity client developer with 14 years of experience in mobile and live-service games. I write about optimization problems I keep encountering in production.
Experiment files
- Repository: hellohanostudio/BuildAnalyzer
- Automation:
ExperimentBuildRunner.cs - Raw results:
experiment-results-run1.csvandexperiment-results-run2.csv - Per-step BuildReport exports:
Results/raw - Unity API:
BuildReport.packedAssetsandPackedAssetInfo - Font: Noto Sans KR from Google Fonts, SIL Open Font License 1.1


Top comments (0)