Mobile Development 19 min read

How to Slash Unreal Engine Android APK Size: Proven UE4/UE5 Optimization Techniques

This article explains how to reduce Unreal Engine Android package size and native library memory usage by applying a series of build‑time and resource‑trimming strategies—including native lib compression, code size reduction, relocation table compression, and selective asset packaging—while preserving runtime performance.

Tencent Technical Engineering
Tencent Technical Engineering
Tencent Technical Engineering
How to Slash Unreal Engine Android APK Size: Proven UE4/UE5 Optimization Techniques

Package Size Distribution

The Android APK mainly consists of three parts: executable code (e.g., lib/arm64-v8a), game resources packed into main.obb (Pak files and DirectoriesToAlwaysStageAsNonUFS), and third‑party component files copied into the APK.

Each part requires a dedicated optimization approach.

Compress NativeLibs

When installing an APK, native libraries can be handled in two ways:

Extract .so files to the app’s internal storage ( /data/app/<package_name>/lib/).

Load .so directly from the APK, which speeds up installation.

The compression behavior is controlled by the extractNativeLibs flag in AndroidManifest.xml. In newer engine versions you can set bExtractNativeLibs in AndroidRuntimeSettings. For older versions (< 4.27) you may need to replace extractNativeLibs with useLegacyPackaging in Gradle and force the value via UPL:

<addAttribute tag="application" name="android:extractNativeLibs" value="true"/>
Note: This only controls whether the .so is compressed in the APK; it does not reduce the actual .so size.

Code Size Optimization

For Android the goal is to shrink the size of each .so, especially libUE4.so / libUnreal.so, while keeping runtime performance acceptable.

Disable Unnecessary Modules

// disable modules
bUseChaos = false;
bCompileChaos = false;
bCompileAPEX = false;

Control Inlining

Inlining improves performance but enlarges the .text section. You can disable it by setting bUseInlining = false in target.cs (iOS/Linux/Mac/Win) and adding the -fno-inline-functions flag for Android:

if (TargetInfo.Platform == UnrealTargetPlatform.Android)
{
    if (bUseInlining)
        AdditionalCompilerArguments += " -finline-functions";
    else
        AdditionalCompilerArguments += " -fno-inline-functions";
}
Disabling inline may slightly affect performance for hot‑path functions, but the impact is usually negligible.

Disable Exception Handling

bEnableExceptions = false;

This removes the .eh_frame section from the binary.

Use O3 or Oz Optimization

// optimization level
if (!CompileEnvironment.bOptimizeCode)
    Result += " -O0";
else
{
    if (CompileEnvironment.bOptimizeForSize)
        Result += " -Oz"; // size‑first
    else
        Result += " -O3"; // performance‑first
}
-O3

favors performance (aggressive inlining, loop unrolling); -Oz favors size (avoids inlining, keeps loops).

Enable LTO

bAllowLTCG = true; // LTO
if (bAllowLTCG)
    AdditionalCompilerArguments += " -flto=thin";

LTO removes dead code and enables cross‑module optimizations.

Strip Exported Symbols

By default all symbols are exported. For UE only a few JNI entry points need to be kept. Use a version‑script and pass it to the linker:

string VersionScriptFile = GetVersionScriptFilename();
using (StreamWriter Writer = File.CreateText(VersionScriptFile))
{
    Writer.WriteLine("{ global: Java_*; ANativeActivity_onCreate; JNI_OnLoad; local: *; };");
}
AdditionalLinkerArguments += " -Wl,--version-script=\"" + VersionScriptFile + "\"";

Data Optimization

After applying the above code‑size techniques, the original libUE4.so size of 258 MB (Shipping) was reduced to 146 MB, and its compressed size dropped from 74.3 MB to 44.67 MB, saving 29.63 MB.

Original size: 258M → 146M
Compressed size: 74.3M → 44.67M

Relocation Table Compression

For MinSDKVersion >= 28 (Android 9) enable RELR compression:

AdditionalCompilerArguments += " -fPIC";
AdditionalLinkerArguments += " -Wl,--pack-dyn-relocs=android+relr,--use-android-relr-tags";

Verify with readelf -d libUE4.so for a RELR entry. This reduces the relocation table from 25.82 MB to 280 KB, shaving ~25 MB off the .so and ~4 MB from the APK.

SDK 23 Alternative

AdditionalCompilerArguments += " -fPIC";
AdditionalLinkerArguments += " -Wl,--pack-dyn-relocs=android";

Works for MinSDKVersion >= 23 and still yields a noticeable size reduction.

Resource Trimming

Third‑Party Plugin Files (GVoice Example)

Identify unused model files (e.g., wave_dafx_data.bin, wave_3d_data.bin, cldnn_spkvector.mnn) and remove them. Keep only required files such as libgvoicensmodel.bin. Adjust the copy logic in GVoice_APL.xml to copy only the needed files:

<resourceCopies>
    <log text="Start copy res..."/>
    <!-- Only copy libgvoicensmodel.bin and config.json -->
    <copyFile src="$S(PluginDir)/../GVoiceLib/Android/assets/libgvoicensmodel.bin" dst="$S(BuildDir)/assets/libgvoicensmodel.bin" force="true"/>
    <copyFile src="$S(PluginDir)/../GVoiceLib/Android/assets/config.json" dst="$S(BuildDir)/assets/config.json" force="true"/>
</resourceCopies>

Game Assets

Assets are either packed into pakchunk0 or placed in DirectoriesToAlwaysStageAsNonUFS (e.g., Content/Movies). Optimize by:

Keeping only essential engine assets ( /Engine shaders, ini files, startup map, etc.).

Removing non‑startup resources.

Lazy‑loading optional assets (e.g., localization files).

Splitting fonts and other large assets for dynamic download.

Configure DefaultEngine.ini to exclude .pak files from the APK on Android:

; Config/DefaultEngine.ini
[/Script/AndroidRuntimeSettings.AndroidRuntimeSettings]
+ObbFilters=-*.pak
+ObbFilters=pakchunk0-*

For other platforms a custom filter (e.g., the “HotChunker” extension) can be used.

Overall Results

Combining all the above techniques reduced the game’s APK from 1.23 GB to ~130 MB, the original libUE4.so from 258 MB to 132 MB, and runtime memory usage by dozens of megabytes, while keeping full functionality and enabling dynamic asset delivery.

Additional References

UE Plugin & Tool Development: Core Concepts

Resource Management: Reshaping UE Package Splitting

UE Resource Management: Engine Packaging Analysis

Reducing Packaged Game Size (Epic Docs)

Google Play App Size Limits

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

AndroidpackagingUnreal EngineAPK size optimizationUE4
Tencent Technical Engineering
Written by

Tencent Technical Engineering

Official account of Tencent Technology. A platform for publishing and analyzing Tencent's technological innovations and cutting-edge developments.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.