Back to Blog
Optimization & Build Issues
2026-08-10 · Updated October 2026
10 min read

How to Reduce Unity Mobile Game Build Size

Analyze the Build Report, configure texture compression per platform, manage audio and code stripping, and use Addressables to reduce Unity mobile build sizes effectively.

UnityOptimizationMobilePerformanceC#
Rohit Rewani
Rohit Rewani — Unity Developer
Unity • C# • Mobile Games • Multiplayer • AR
How to Reduce Unity Mobile Game Build Size cover visual

Why Build Size Matters

A large application size reduces conversion at the point of install. Players on mobile data connections are more likely to abandon a download when warned about file size, and app stores enforce their own thresholds.

On Android, Google Play applies a 200 MB warning for apps delivered over cellular. If you publish as an Android App Bundle (AAB), Google Play handles delivery itself and can reduce the download significantly through split APKs — delivering only the assets relevant to the user's device ABI and screen density. This threshold applies to the compressed download, not the installed size, and is subject to change; check the current Play Console policies for the latest value.

On iOS, Apple currently documents a 200 MB over-the-air download limit; builds exceeding it are flagged in App Store Connect. The App Store also displays the app size prominently on the product page, which affects install rates.

The practical takeaway is that you are optimising for both the download size (what the store delivers) and the installed size (what remains on the device after decompression). These can differ significantly, particularly with compressed audio and texture assets.

APK vs AAB: Choosing Your Delivery Format

Unity can build either an APK or an Android App Bundle (AAB). Understanding the difference matters for size optimisation.

APK (Android Package): A single monolithic file. By default, Unity builds a fat APK that includes native libraries for all enabled ABIs (typically arm64-v8a and armeabi-v7a; x86 and x86_64 are optional and rarely needed for shipping builds). It is useful for local device installs and sideloading during development, but the upload and install size tends to be larger than what store delivery would provide.

AAB (Android App Bundle): Required by Google Play for new apps and games since August 2021. Rather than shipping a single fat APK, you upload the bundle and Play handles splitting it into device-optimised APKs at delivery time. A device receives only the native library for its ABI and only the textures matching its supported compression format. For games targeting multiple texture compression formats (ASTC + ETC2 fallback), the AAB approach alone can meaningfully reduce the delivered download size.

Enable AAB in Player Settings > Publishing Settings > Build App Bundle (Google Play).
tipWhen using AAB, you can test locally using bundletool to simulate the device-specific APK that Google Play would deliver. This gives you an accurate picture of the actual download size rather than the full bundle size.

Reading the Build Report

Before optimising anything, you need to know what is actually taking up space. The Build Report gives you a breakdown by asset type.

Where to find it: After a build completes, open the Editor Log via Console > Open Editor Log (or find it at %LocalAppData%\Unity\Editor\Editor.log on Windows). Search for Build Report to jump to the summary section.

The report lists asset categories (Textures, Audio, Meshes, Shaders, Scripts, Other Assets) with their sizes in MB, plus the percentage of total build. Below the summary, individual assets are listed by size, descending. This is where you identify the actual large files rather than guessing.

Unity 6 and newer also include a graphical Build Report window available under Window > Build Report, which provides a tree view of included assets and their contribution to build size.
infoRun the Build Report on a Release build with the same settings you use for store submission. Debug builds include additional symbols and may not reflect what your players download.

Texture Compression: ASTC, ETC2, and Per-Platform Targeting

Textures are typically the largest single category in a mobile build. The choice of compression format affects both quality and file size.

ASTC (Adaptive Scalable Texture Compression) offers good quality-to-size ratios and is supported on most modern iOS and Android devices. It supports block sizes from 4×4 to 12×12, with larger blocks giving smaller files at the cost of quality. On iOS, ASTC is supported on A8-chip devices and newer. On Android, ASTC requires hardware support from the GPU and is not universally available across all Android devices — particularly on older or low-end handsets. Unity will fall back to a compatible format on unsupported hardware if you configure split texture compression in your build settings.

ETC2 is the widely supported baseline for Android, available on all devices running OpenGL ES 3.0 or higher (Android 4.3+). It provides broad compatibility at the cost of some efficiency compared to ASTC, and has limited support for alpha channels (ETC2 RGBA8 is available but less efficient than ASTC for alpha-heavy textures).

Per-platform targeting in Unity: In the Texture Importer settings, you can override the compression format independently for each build target. Under the Android platform tab, you can select a different format than the iOS tab. For broad Android compatibility, consider enabling multiple compression format targets via the Build Settings texture compression override, which allows the AAB to carry both ASTC and ETC2 assets and deliver the appropriate one per device.

Automating Texture Size Caps with an Editor Script

If a specific asset folder consistently accumulates oversized textures during development, you can automate a cap using an Editor script. The following example targets all Texture2D assets in Assets/UI and sets a 512 px maximum import size:
warningThis script modifies the default importer settings, which applies across all build targets including PC and console. If you only want to cap the size for mobile, use SetPlatformTextureSettings() to override the max texture size per platform rather than setting the global maxTextureSize. Also confirm that no textures in the folder are intentionally large (e.g., full-screen splash backgrounds) before running this across a whole directory.
csharp
using UnityEditor;
using UnityEngine;

public class UIAssetOptimizer : EditorWindow {
    [MenuItem("Tools/Cap UI Textures at 512")]
    static void OptimizeUI() {
        string[] guids = AssetDatabase.FindAssets("t:Texture2D", new[] {"Assets/UI"});
        foreach (string guid in guids) {
            string path = AssetDatabase.GUIDToAssetPath(guid);
            TextureImporter importer = AssetImporter.GetAtPath(path) as TextureImporter;
            
            if (importer != null && importer.maxTextureSize > 512) {
                importer.maxTextureSize = 512;
                importer.SaveAndReimport();
            }
        }
    }
}

The Resources Folder and Addressables

Unity includes everything inside a Resources folder in the final build, regardless of whether any scene actually references it at runtime. This is one of the most common sources of unintentional build bloat in projects that have grown organically.

What to do: Move assets out of Resources and manage them as direct scene references, or use Addressables for dynamic loading. The Addressable Asset System allows you to configure assets as local bundles (shipped with the build) or remote bundles (downloaded at runtime), giving you control over what is included in the initial install versus what is deferred.

For simpler projects that do not need content streaming, moving assets out of Resources and referencing them directly via scene references or ScriptableObjects is enough to prevent unnecessary inclusion. Unity only packages assets that are explicitly referenced by a scene in the build, or that reside in a Resources or StreamingAssets folder. Note that StreamingAssets content is always packaged and is not a substitute for Addressables if you want to control download timing.

Audio Optimisation

Audio is frequently the second-largest contributor to build size after textures. Unity provides per-clip compression settings that are worth reviewing.

Background music: Use Vorbis compression for long-form music tracks and set the Load Type to Streaming. Streaming reads audio data from disk at playback time rather than loading the entire decompressed clip into memory at startup. While this drastically reduces runtime memory usage, it does not reduce the actual build or download size — only the compression format (Vorbis/AAC) does that. On iOS, Unity converts Vorbis to AAC at build time.

Sound effects: Short sound effects can use ADPCM for a reasonable balance between size and decode performance, or Compressed In Memory with Vorbis for maximum compression at the cost of a small decode overhead on play.

Mono vs Stereo: For sound effects that do not require spatial positioning, setting the clip to Force To Mono halves the stored audio data. Confirm the effect sounds acceptable in mono before applying this broadly.

Sample Rate Reduction: Music and ambient tracks rarely need 44.1 kHz on a phone speaker or earbuds at typical mobile listening volumes. Reducing to 22,050 Hz for non-critical audio can cut audio asset size measurably with minimal perceptible quality loss.

Meshes and Shaders

Two less-obvious contributors to build size are meshes and shaders.

Meshes: Import only the data your game uses. In the Mesh Import settings, disable Read/Write Enabled if you do not access mesh data at runtime via script — this halves the runtime memory cost of the mesh and also reduces the asset data Unity stores. Disable Normals or Tangents for meshes that use unlit shaders where lighting data is unused.

Shaders: Unity compiles every keyword combination of a shader that is referenced in the build, which can produce a large number of variants. To reduce this, use Edit > Project Settings > Graphics > Shader Stripping to actively strip unused variants (e.g., stripping fog or unused lighting modes). Conversely, a Shader Variant Collection is used to explicitly define and preload the variants you actually do need, ensuring they aren't stripped by accident. For projects on the built-in render pipeline, managing stripping and variant collections effectively can meaningfully reduce shader compile time and build output size.

Managed Code Stripping

Unity's IL2CPP and Mono backends include code stripping, which removes unused engine and library code from the build. You configure this in Player Settings > Other Settings > Managed Stripping Level.

Minimal is the default setting in Unity 6 for both Mono and IL2CPP. It is the safest option as it removes very little code. Low is recommended if you want to strip clearly unused Unity engine modules. Medium and High strip much more aggressively, greatly reducing build size but requiring thorough device testing to catch missing type exceptions at runtime.

If you use serialisation libraries, dependency injection frameworks, or Unity events that invoke methods by name, code stripping can remove code that appears unreferenced at link time but is invoked at runtime. Preserve these types using a link.xml file placed anywhere inside your Assets folder (Unity discovers it automatically):
infoStart with Managed Stripping Level: Minimal (the Unity 6 default) and run a full QA pass on a device build before moving to Low, Medium, or High. Stripping issues often appear as NullReferenceExceptions or missing type errors at runtime rather than compile time.
xml
<linker>
  <!-- Preserve a specific type in a third-party library -->
  <assembly fullname="MySDK">
    <type fullname="MySDK.ReflectedHelper" preserve="all" />
  </assembly>

  <!-- Preserve all types in an assembly -->
  <assembly fullname="Newtonsoft.Json" preserve="all" />
</linker>

Build Size Reduction Checklist

A quick reference for reviewing a Unity mobile project build footprint:
  • Build Report reviewed — identified the top 10 largest assets by category before optimising.
  • Publishing format — using AAB for Google Play, not a fat APK.
  • Texture compression — ASTC enabled for modern devices; per-platform overrides set correctly for iOS and Android.
  • Texture max sizes — UI textures capped appropriately; no unintentionally large assets in build.
  • Resources folder audited — only assets that must load at startup are in Resources; remainder moved to Addressables or direct references.
  • Audio compression — music uses Vorbis/streaming; SFX use ADPCM or Compressed In Memory; mono applied where appropriate.
  • Mesh import settings — Read/Write disabled for static meshes; normals/tangents stripped where not needed.
  • Shader variants — unused shader variants stripped via Project Settings > Graphics.
  • Managed Code Stripping — set to Minimal or above; link.xml created for any types known to use reflection.
  • For related SDK-related build failures that surface during this process, see the Unity Android build errors guide.

Official References