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

雖然 Unity 中的核心遊戲邏輯是以 C# 編寫 (使用 IL2CPP 編譯),但 Android 版本包含大量 Java 和 Kotlin 位元碼 (classes.dex),用於處理 UnityPlayerActivity 生命週期事件、Google Play 服務、帳單、廣告和社群 SDK。

啟用 R8 (Android Gradle 外掛程式 (AGP) 中的預設程式碼縮減器和最佳化工具),可移除未使用的類別和方法,並最佳化位元碼。這不僅能縮減應用程式下載大小,還能減少記憶體對應 (mmap) DEX 頁面的執行階段記憶體用量,以及基準 Java 程序負擔,進而減輕實體記憶體壓力,並減少記憶體不足終止工具 (LMK) 終止作業。Google Play 也會透過 Android Vitals 的 DEX 程式碼最佳化指標,監控遊戲的 DEX 最佳化程度。

預設行為和 Unity 版本支援

在 Unity 中,建立新專案時,發布和偵錯版本的程式碼壓縮功能預設為停用 (false)。

Unity 首次在 Unity 2020.1.0f1 中推出 R8 做為選用切換鈕。自 Unity 2022.2.0f1 起 (並向後移植至 Unity 2021.3.41f1 LTS),Unity 將隨附的工具鍊升級至 AGP 7.1.2 以上版本、移除舊版 ProGuard 支援,並在啟用壓縮功能時一律執行 R8。

Unity 版本 隨附 AGP 預設版本 R8 支援和必要設定
2019.4 LTS 以下版本 3.4 以前的版本 已停用 (false) 不支援 (僅限舊版 ProGuard)。
2020.1.0f1 至 2021.3.40f1 3.4 至 4.0 已停用 (false) 選用 (預設為 ProGuard)。啟用「Minify」>「Release」和「Use R8」。
2021.3.41f1 以上版本 (2021 LTS) 7.1 以上版本 已停用 (false) 僅限 R8。啟用「Minify」>「Release」,即可自動執行 R8。
2022.2.0f1 至 Unity 6 以上版本 7.1 至 8.x 已停用 (false) 僅限 R8。啟用「Minify」>「Release」,即可自動執行 R8。

在 Player Settings 中啟用 R8

如要為發布子版本啟用 R8 程式碼縮減和最佳化功能,請按照下列步驟操作:

  1. 在 Unity 編輯器中,依序開啟「Edit」>「Project Settings」,然後選取「Player」。
  2. 選取「Android」分頁標籤,然後依序展開「Publishing Settings」>「Build」。
  3. 在「Minify」部分,設定 Unity 版本的選項:
    • Unity 2021.3.41f1+ 和 2022.2.0f1+:選取「Release」。Unity 會在 minifyReleaseWithR8 Gradle 工作期間自動執行 R8。
    • Unity 2020.1.0f1 至 2021.3.40f1:同時選取「Release」和「Use R8」。

如果您使用 C# 編輯器指令碼自動執行建構作業,請透過 PlayerSettings.Android 設定這些屬性:

using UnityEditor;

public static class AndroidBuildConfig
{
    public static void EnableR8ForRelease()
    {
        PlayerSettings.Android.minifyRelease = true;

        // Required only in Unity 2020.1.0f1 to 2021.3.40f1 and 2022.1 or earlier
        // (In Unity 2021.3.41f1+ and 2022.2+, R8 is always used when minification is enabled)
#if !UNITY_2022_2_OR_NEWER
        PlayerSettings.Android.minifyWithR8 = true;
#endif
    }
}

新增 JNI 和反射的保留規則

使用 AndroidJavaClass 或 AndroidJavaObject 從 C# 指令碼動態叫用的 Java 類別和方法沒有靜態 Java 呼叫網站。如果沒有明確的保留規則,R8 可能會將這些類別視為未使用,並將其移除或重新命名。

如要保留自訂 Java 橋接器:

  1. 依序前往「專案設定」>「Player」>「Android」>「Publishing Settings」>「Build」,然後啟用「Custom Proguard File」。
  2. 開啟產生的 Assets/Plugins/Android/proguard-user.txt 檔案。
  3. 為透過 JNI 存取的類別或第三方外掛程式所需的類別新增 -keep 規則:
# Keep custom Java classes invoked from C# using JNI bridges
-keep class com.example.yourgame.** { *; }

# Keep callback interfaces passed between C# and Java
-keep interface com.example.yourgame.IPluginCallback { *; }

排解常見問題

本節說明如何在 Unity 中使用 R8 時,解決常見的建構和執行階段問題。

Missing classes detected while running R8 項建構錯誤

在採用 AGP 7.0 以上版本 (2021.3.41f1+ 和 2022.2+) 的 Unity 版本中,R8 會強制執行嚴格的缺類檢查。如果建構作業因這項錯誤而失敗,請檢查建構輸出目錄 (位於 Library/Bee/Android/Prj/.../build/outputs/mapping/release/missing_rules.txt 或 Temp/gradleOut/... 下方) 中產生的 missing_rules.txt 檔案,並將必要的依附元件或規則新增至 proguard-user.txt。如要進一步瞭解如何編寫保留規則,請參閱「自訂要保留的程式碼」。

R8 完整模式與第三方外掛程式的相容性

在 AGP 8.0 以上版本 (Unity 6+) 中,系統預設會啟用 R8 完整模式,執行更積極的最佳化。如果舊版 Android 外掛程式在執行階段因反射問題而失敗,請更新外掛程式的 ProGuard 規則,或將 R8 還原為相容模式:

  1. 在「Publishing Settings」>「Build」中,啟用「Custom Gradle Properties Template」。
  2. 開啟 Assets/Plugins/Android/gradleTemplate.properties 並新增下列屬性:
android.enableR8.fullMode=false