R8 を使用して Unity コードを圧縮、最適化する

Unity のコアゲーム ロジックは C# で記述されていますが(IL2CPP でコンパイル)、Android ビルドには、UnityPlayerActivity ライフサイクル イベント、Google Play 開発者サービス、課金、広告、ソーシャル SDK を処理するための Java と Kotlin のバイトコード(classes.dex)が大量に含まれています。

Android Gradle プラグイン(AGP)のデフォルトのコード圧縮ツールおよびオプティマイザーである R8 を有効にすると、未使用のクラスとメソッドが削除され、バイトコードが最適化されます。これにより、アプリのダウンロード サイズが小さくなるだけでなく、メモリマップド(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 とリフレクションの keep ルールを追加する

AndroidJavaClass または AndroidJavaObject を使用して C# スクリプトから動的に呼び出される Java クラスとメソッドには、静的な Java 呼び出しサイトがありません。明示的な keep ルールがない場合、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