DEV Community

Cover image for What Actually Makes a Unity Build So Large?
HanoStudio
HanoStudio

Posted on

What Actually Makes a Unity Build So Large?

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;
Enter fullscreen mode Exit fullscreen mode

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

Bar chart of APK size after all eight controlled changes

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.so compressed size grew by about 0.36 MiB.
  • global-metadata.dat compressed 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:

  1. Final artifact bytes
  2. Packed asset contributions
  3. Native and managed code or metadata changes

Unity Editor evidence window showing measured APK, packed asset, importer, and repeatability data

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

Top comments (0)