雖然 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 開始,Unreal Engine 的 UEDeployAndroid.cs 預設會將 minifyEnabled true 插入產生的 Android 發布子版本建構設定 (buildAdditions.gradle)。由於 UE 4.25 將隨附的工具鍊升級至 AGP 4.0.0,因此在 UE 4.25 以上版本的所有發布 (運送和發布) 版本中,R8 預設為啟用 (true),不需額外設定。
| Unreal Engine 版本 | 隨附 AGP | 預設版本 | 偵錯預設值 | 行為 |
|---|---|---|---|---|
| UE 4.21 以下版本 | 舊版 Gradle 或 Ant | 已停用 (false) |
已停用 (false) |
引擎未插入 minifyEnabled 設定。 |
| UE 4.22 至 4.24 | 3.4 以前的版本 | 已啟用 (ProGuard) | 已停用 (false) |
發布子版本預設啟用 minifyEnabled true (執行 ProGuard)。 |
| UE 4.25 至 5.3 | 4.0.0 | 啟用 (R8) | 已停用 (false) |
AGP 4.0 採用版本預設會在發布子版本中執行 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 最佳化管道。 |
發布版本和偵錯版本的差異
UnrealBuildTool (UEDeployAndroid.cs) 會針對發布版本和偵錯版本,以不同方式設定產生的 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),以保留快速建構疊代和符號偵錯。
使用 Unreal 外掛程式語言 (UPL) 新增保留規則
由於 R8 會在 UE 4.25 以上版本的發布子版本中自動執行,因此您必須保留僅透過 C++ JNI (JNIEnv->FindClass、GetMethodID) 或資訊清單存取的 Java 類別。沒有 Java 呼叫網站的類別會被視為未使用,並由 R8 移除,這可能會導致在開發版本中運作的功能在運送版本中失敗,並顯示 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 會強制執行嚴格的缺少類別檢查。如果封裝失敗並顯示這項錯誤,請檢查中繼建構目錄 (位於 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>