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

AndroidpackagingUnreal EngineNative librariesAPK 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

login 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.