使用 R8 縮減及最佳化 Unreal Engine 程式碼

雖然 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>