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.
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
.sofiles to the app’s internal storage (
/data/app/<package_name>/lib/).
Load
.sodirectly from the APK, which speeds up installation.
The compression behavior is controlled by the
extractNativeLibsflag in
AndroidManifest.xml. In newer engine versions you can set
bExtractNativeLibsin
AndroidRuntimeSettings. For older versions (< 4.27) you may need to replace
extractNativeLibswith
useLegacyPackagingin 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
.textsection. You can disable it by setting
bUseInlining = falsein
target.cs(iOS/Linux/Mac/Win) and adding the
-fno-inline-functionsflag 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_framesection 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
} -O3favors performance (aggressive inlining, loop unrolling);
-Ozfavors 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.sosize 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.67MRelocation 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.sofor a
RELRentry. This reduces the relocation table from 25.82 MB to 280 KB, shaving ~25 MB off the
.soand ~4 MB from the APK.
SDK 23 Alternative
AdditionalCompilerArguments += " -fPIC";
AdditionalLinkerArguments += " -Wl,--pack-dyn-relocs=android";Works for
MinSDKVersion >= 23and 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.xmlto 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
pakchunk0or placed in
DirectoriesToAlwaysStageAsNonUFS(e.g.,
Content/Movies). Optimize by:
Keeping only essential engine assets (
/Engineshaders, 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.inito exclude
.pakfiles 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.sofrom 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
Tencent Technical Engineering
Official account of Tencent Technology. A platform for publishing and analyzing Tencent's technological innovations and cutting-edge developments.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.