虽然 Unreal Engine 中的核心游戏逻辑是用 C++ 或蓝图编写的,但 Android 打包会编译 Java 和 Kotlin 字节码 (classes.dex),以处理 GameActivity 生命周期事件、Google Play 服务、结算、音频和分析插件。
R8 是 Android Gradle 插件 (AGP) 中的默认代码缩减器和优化器,可移除未使用的类和方法,并优化字节码。这不仅可以缩减软件包下载大小,还可以减少内存映射 (mmap) DEX 页面和基准 Java 进程开销的运行时内存占用,从而缓解物理内存压力和低内存终止守护程序 (LMK) 终止。Google Play 还会通过 Android Vitals 中的 DEX 代码优化指标监控游戏的 DEX 优化级别。
默认行为和 Unreal Engine 版本支持
从 UE 4.22.0 开始,虚幻引擎的 UEDeployAndroid.cs 默认会将 minifyEnabled true 注入生成的 Android 发布 build 配置 (buildAdditions.gradle) 中。由于 UE 4.25 将捆绑的工具链升级到了 AGP 4.0.0,因此在 UE 4.25 及更高版本中,所有发布(交付和分发)build 默认启用 R8 (true),无需额外设置。
| Unreal Engine 版本 | 捆绑式 AGP | 默认版本 | 默认调试 | 行为 |
|---|---|---|---|---|
| UE 4.21 及更低版本 | 旧版 Gradle 或 Ant | 已停用 (false) |
已停用 (false) |
引擎未注入 minifyEnabled 配置。 |
| UE 4.22 至 4.24 | 早于 3.4 | 已启用 (ProGuard) | 已停用 (false) |
minifyEnabled true 在发布 build 中默认启用(运行 ProGuard)。 |
| UE 4.25 至 5.3 | 4.0.0 | 已启用 (R8) | 已停用 (false) |
AGP 4.0 采用在发布 build 中默认运行 R8 的做法。 |
| UE 5.4 至 5.7 | 7.4.2 | 已启用 (R8) | 已停用 (false) |
AGP 7.x 移除了旧版 useProguard 选项;R8 专门运行。 |
| UE 5.8 (5.8.3+) | 8.13.0 | 已启用 (R8) | 已停用 (false) |
默认使用 AGP 8.x 和现代 R8 优化流水线。 |
Release build 与 调试 build 的差异
UnrealBuildTool (UEDeployAndroid.cs) 会针对发布 build 和调试 build 以不同的方式配置生成的 buildAdditions.gradle 文件:
buildTypes {
release {
signingConfig signingConfigs.release
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
debug {
debuggable true
signingConfig signingConfigs.debug
}
}
- 发布(配送或分发):默认设置
minifyEnabled true并应用proguard-rules.pro,运行 R8 代码缩减和混淆。 - 调试(开发):启用
debuggable true并省略minifyEnabled(默认为false),以保留快速 build 迭代和符号调试。
使用 Unreal 插件语言 (UPL) 添加 keep 规则
由于 R8 会在 UE 4.25 及更高版本的发布 build 上自动运行,因此您必须保留仅通过 C++ JNI(JNIEnv->FindClass、GetMethodID)或清单访问的 Java 类。没有 Java 调用网站的类会被视为未使用,并被 R8 剥离,这可能会导致在开发 build 中正常运行的功能在发布 build 中因 ClassNotFoundException 或 NoSuchMethodError 而失败。
在 Unreal 插件语言 (UPL) XML 文件中使用 <proguardAdditions> 标记,以便在打包期间将自定义保留规则合并到 proguard-rules.pro 中。将以下代码块添加到项目或插件 *_UPL.xml 文件中:
<root xmlns:android="http://schemas.android.com/apk/res/android">
<proguardAdditions>
<insert>
-keep class com.epicgames.unreal.** { *; }
-keep class com.example.plugin.** { public *; }
-dontwarn com.example.plugin.**
</insert>
</proguardAdditions>
</root>
排查常见问题
本部分介绍了如何解决在 Unreal Engine 中使用 R8 时遇到的常见打包和运行时问题。
暂时停用 R8 以进行调试
如需确定仅在发布版本中发生的崩溃是否由 R8 剥离了必需的类所致,请在 UPL 文件的 <gradleProperties> 下插入 DISABLE_MINIFY=1。
如果存在,UEDeployAndroid.cs 会生成 minifyEnabled false:
<gradleProperties>
<insert>
DISABLE_MINIFY=1
</insert>
</gradleProperties>
Missing classes detected while running R8 个打包错误
在 UE 5.4 及更高版本 (AGP 7.4.2+) 中,R8 会强制执行严格的类缺失检查。如果打包失败并显示此错误,请检查中间 build 目录(位于 Intermediate/Android/.../gradle/app/build/outputs/mapping/release/missing_rules.txt 下)中的 missing_rules.txt,并将缺少的库依赖项或必需规则添加到 UPL 文件中的 <proguardAdditions>。
R8 完整模式与第三方 SDK 的兼容性
在 UE 5.8 及更高版本 (AGP 8.13.0+) 中,R8 完整模式默认处于启用状态,以执行更积极的优化。如果旧版第三方 Android SDK 在运行时因反射问题而失败,请更新插件的 ProGuard 规则,或通过向 UPL 文件添加以下属性,将 R8 还原为兼容模式:
<gradleProperties>
<insert>
android.enableR8.fullMode=false
</insert>
</gradleProperties>