渋谷ほととぎす通信

「Unityをわかりやすく」初心者のためのゲーム作りブログ

【Android】IL2CPPビルド失敗時に考えられる2つの理由

【Android】IL2CPPビルド失敗時に考えられる2つの理由

こんにちは、Unityエンジニアのオオバです。

お悩みさん
お悩みさん
  • UnityでAndroid向けのIL2CPPビルドが失敗してしまう
  • オオバ
    オオバ
    本記事ではこれらの悩みを解決します。

    UnityでAndroidスマホ向けアプリをビルドする際は、IL2CPPビルドが必須です。

    👉DOTweenの教科書を読んでUnityアニメーションをプログラミングしてみよう!

    なぜIL2CPPビルドする必要あるのか?

    なぜAndroidビルドにIL2CPPを使用するかですが、結論、 64ビット版のアプリ書き出しがIL2CPPでしかできないから です。つまりMonoビルドでは32ビット版アプリしか書き出せないということです。

    Androidのビルド方法には「Mono」と「IL2CPP」の2つのやり方があります。MonoでビルドしたAndroidアプリはMonoランタイム上で動きます。一方IL2CPPはC#からC++に一度変換しAndroid用のバイナリに書き出されます。

    Monoは実行時にネイティブコードがコンパイルされ、IL2CPPは事前にコンパイルされているというのが仕組み上大きな違いです。

    開発面ではMonoビルドの方がIL2CPPに比べ圧倒的にビルド時間が短く利便性は高いです。一方アプリとしてのセキュリティ面はIL2CPPの方が高いです(IL2CPPだけに頼るだけではダメですが)。

    話を戻しましてMonoビルドの32ビット版アプリでも良いではないかと思うかもしれません。しかしGoogle Playがそれを許さないのです。

    2019 年 8 月 1 日以降、Google Play で公開するアプリは 64 ビット アーキテクチャをサポートする必要があります。

    📚 参考サイト : 64 ビット アーキテクチャのサポート  |  Google Play  |  Android Developers

    上記のとおりGoogle Playは2019年8月1日以降64ビット版アプリのサポートを必須としました。つまりUnityでスマホゲームを作る場合は IL2CPPビルド一択 というわけです。

    IL2CPPでビルドする方法

    IL2CPPでビルドする方法は簡単です。 メニューFile > Build Settings > Player Settings からPlayer Settingを開きます。

    【Android】IL2CPPビルド失敗時に考えられる2つの理由_0

    Scripting Backendを「IL2CPP」にします。 そして64ビット版アプリを書き出す場合は 「ARM64」 を選択しましょう。
    ※Monoビルドの場合は、ARM64が選べないのです

    Android向けIL2CPPビルドに失敗する2つの理由

    ではここから本題のAndroid向けIL2CPPビルドに失敗する2つの理由について解説していきます。

    【Android】IL2CPPビルド失敗時に考えられる2つの理由_1

    ちなみにアプリのビルドは メニューFile > Build Settings からBuild Settingsウィンドウを開き、「Build」または「Build And Run」ボタンを押すだけです。

    Buildボタンの場合はapkファイルが作成されます。Build And RunボタンはAndroid端末をUSBケーブルで繋ぐことで直接ビルド後インストールできて便利です。

    もしAndroid実機ビルドが上手くいかないという方はこちらの記事を読んでみてください。

    そんなAndroid向けIL2CPPビルドですが、失敗してしまうときの理由はこちらの2つが考えられます。

    Android向けIL2CPPビルドに失敗する2つの理由

    ①Unityプロジェクトのパスに日本語名が含まれている

    ②シンボル設定ミス

    では1つずつ解説していきます。

    理由①Unityプロジェクトのパスに日本語名が含まれている

    ビルドしようとしているUnityプロジェクトのパスに 日本語 が含まれるとIL2CPPビルドは失敗します。

    例えば次のようなパスにUnityプロジェクトを配置するとIL2CPPビルドは失敗します。

    Users/ohbashunsuke/workspace/てすと/unity-project  
    

    Unityプロジェクトにたどり着く前に「てすと」という日本語名パスが邪魔をしているのです。

    Users/ohbashunsuke/workspace/てすと/unity-project  
    ↓  
    Users/ohbashunsuke/workspace/test/unity-project  
    

    直し方はパスを変更するだけです。上記の例では「てすと」を「test」に変更しました。しかし、Unityプロジェクトのパスを変更するとUnity Hubから起動できなくなります。

    【Android】IL2CPPビルド失敗時に考えられる2つの理由_2

    パスを変更したUnityプロジェクトは、Unity Hubの 「開くボタン」 から再度Unity Hubに登録してあげましょう。

    【Android】IL2CPPビルド失敗時に考えられる2つの理由_3

    不要になったプロジェクトは 「リストからプロジェクトを削除」 をクリックして削除しましょう。

    ビルドログから日本語がマズい理由がわかる

    エラーとはエラーログが全て教えてくれます。 ビルドに失敗したときのログを見てみましょう。次のエラーは所定のパスのファイルを参照できずにエラーを起こしていることが読み取れます。

    【Android】IL2CPPビルド失敗時に考えられる2つの理由_4

    パスの中で「???」が怪しいですよね。実はここには 日本語 が入るのです。

    つまり IL2CPPビルドは日本語パスに対応していないということがわかります。

    ちなみに、UnityプロジェクトのAssetsフォルダ配下の日本語名ファイルはどうなのでしょうか。

    【Android】IL2CPPビルド失敗時に考えられる2つの理由_5

    ↑上図のようにAssetsフォルダ内の日本語ファイルは、結論ビルドに問題は出ません。ただしよっぽどの理由がない限りファイル名に日本語を使う理由はありません。

    理由2.シンボル定義ミス

    IL2CPPビルドエラー2つ目はIL2CPPに限らずMonoビルドでも起こりうる内容です。よくやってしまいがちな無いようなので取り上げています。

    結論から言うと、シンボルの定義ミスです。シンボルとはプラットフォームや環境ごとに動作を切替えたいときに使う手法です。

    #if UNITY_EDITOR
    // Unityエディタ上で動作する  
    #elif UNITY_ANDROID
    // Android実機で動作する  
    #elif UNITY_IOS
    // iOS実機で動作する  
    #else
    // Android、iOS以外の実機(例えばPC)で動作する  
    #endif
    

    上記のような感じで処理を分岐できるのです。特によく使われるのはネイティブプラグインです。ネイティブプラグインとはプラットフォームごとの独自の機能にアクセスする機能です。C#だけではなくC++やObjective-Cを使います。
    例えばAndroid特有の機能にアクセスする場合はAndroid実機だけで動くようにシンボルを設定する必要があるということです。

    ここでミスが起きやすいです。Unityエディタ上ではネイティブプラグインのテストはできません。ビルドして初めてテストが可能です。つまりAndroid向けプラグインを作っているときは良いのですが、iOSでビルドしたときに適切にシンボルが設定されていなくてエラーが起きるといったことはよくあります。

    例えば次のビルド時のエラーログを見てみましょう。

    error: undefined reference to 'Hoge_'  
    

    このエラーは Hoge_ メソッドが存在しないということを指しています。Unityエディタ上では正常で、ビルドして初めて登場するということはシンボル設定が怪しいということがわかります。

    シンボル定義ミスの見つけ方

    ビルドエラーログからシンボルの定義ミスを特定していきます。まずはソースコードから Hoge_ キーワードで全文検索しましょう。すると検索対象付近のシンボルを確認します。

    今回の場合は、iOS向けプラグインなのに #if UNITY_IOS でくくっていなかったのが原因でした。

    【誤】Androidでビルドエラー
    [DllImport("__Internal")]  
    private static extern string Hoge_();  
    
    【修正後】ビルド成功
    #if UNITY_IOS
        [DllImport("__Internal")]  
        private static extern string Hoge_();  
    #endif
    

    シンボル設定はビルドして初めて発覚するエラーなので、プラットフォーム独自の機能を作っているときは、各プラットフォームで正常に動作するかチェックすることが大事です。

    ただSwitch Platformは時間がかかってしまうため、確認はオックになる気持ちはとてもわかります。そんなときの時短テクニックを次の記事にまとめていますので、ぜひ本記事とあわせて読んでみてください。

    Android向けIL2CPPビルドに失敗する2つの理由まとめ

    本記事ではAndroid向けIL2CPPビルドに失敗する2つの理由について解説してきました。記事の内容を簡単にまとめます。

    Android向けIL2CPPビルドに失敗する2つの理由

    ①Unityプロジェクトのパスに日本語が含まれているとエラー

    ②シンボルが適切に設定されているか確認する

    こんな感じです。

    実機ビルドはゲーム開発では必須です。Unityエディタ上でいくら完璧でも実機で確認していないのであればそれはスタート地点にすら立っていない状態です。ぜひIL2CPPビルドエラーで困っている方はこの記事を参考に直してみてください。

    この記事があなたのゲーム開発に少しでもお役に立てたら嬉しいです。

    オススメ記事
    検証環境
    • Unity2020.3.31f1
    参考サイト