渋谷ほととぎす通信

エンジニア社長によるUnityとAIのブログ & エンジニアの生存戦略

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

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

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

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

    UnityでAndroid向けアプリを開発する際、IL2CPPビルドがほぼ必須です。しかしMonoビルドでは成功していたのにIL2CPPに変更した途端にビルドエラーが起きてしまうことってありますよね。

    そこで本記事ではUnity製AndroidアプリにおけるIL2CPPビルドエラー時の対応方法について解説していきます。

    せっかくアプリを作成してもストアに申請できなかったらもったいないですよね。ぜひ最後まで読んでIL2CPPビルドを成功に導いてください。

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

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

    お悩みさん
    お悩みさん
    以前はMonoビルドしていたのになぜIL2CPPが必要なの?

    なぜ今現在AndroidビルドにIL2CPPが必要なのでしょうか?

    結論からお伝えするとGoogle Playの仕様です。

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

    Androidアプリ、ゲームをリリースするためのプラットフォーム「Google Play」が2019年に発表した内容で、64bit版のアプリに対応する必要が出てきました。

    今まで使用してきたMonoビルドでは32bit版しか作成できません。そこでIL2CPPです。

    IL2CPPは64bit版のアプリを書き出すことができるため、今ではIL2CPPは必須設定となったというわけです。

    IL2CPPって何?

    そもそもIL2CPPとは何か、簡単におさらいしてみます。

    IL2CPP(アイエル・トゥー・シー・ピー・ピー)は Intermediate Language To C++ の略で、 Unityが提供しているスクリプト変換技術 のこと。

    IL2CPPを使うことでC#で書かれたスクリプトが中間言語(IL)に変換され、さらにはC++という言語に変換されます。最終的にネイティブコード(各プラットフォーム専用の実行ファイル)になります。

    簡単に言うと 「C# → IL → C++ → ネイティブコード」 という順番でコンパイルされていくのがIL2CPPです。

    IL2CPPとMonoビルドの違いは?

    Unityでは、C#で書いたスクリプトをゲームで動かすために「スクリプティングバックエンド」という変換方式を選ぶ必要があります。代表的なのが「Mono」と「IL2CPP」です。

    それぞれの違いをざっくりまとめると、以下のようになります。

    項目MonoIL2CPP
    変換の流れC# → 中間言語(IL)C# → IL → C++ → ネイティブコード
    実行速度普通(やや遅め)高速になりやすい
    セキュリティ低め(解析されやすい)高め(解析されにくい)
    ビルド時間短い長めになることが多い
    対応プラットフォーム一部(AndroidやWindowsなど)ほぼすべて(iOSなど一部はIL2CPP必須)
    特徴デバッグや開発中に便利リリースビルド向け。パフォーマンス重視

    IL2CPPとMonoどちらを選べばいい?

    Monoビルドのほうがビルド時間が短く開発効率は上がりがちですが、あまりおすすめはしません。基本的には 終始IL2CPPで進めたほうが良い です。

    なぜなら IL2CPPにした途端にエラーが起きる場合があるため です。過去の経験上IL2CPPビルドエラーを解決するためにかなりの時間を消費してきました。その時間を考えるなら最初からIL2CPP設定でビルドした方がトータル開発効率は上がっているのではと思っています。

    また前述の通り、GooglePlayでは64bitアプリ対応が必須のため IL2CPP一択 という感じです。

    IL2CPPでAndroidビルドする方法

    おさらいとしてIL2CPPでAndroidアプリをビルドする方法を解説します。

    【Android】IL2CPPビルド失敗時に考えられる3つの理由_0
    メニューFile > Build Profiles から Build Profiles ウィンドウを開きます。

    【Android】IL2CPPビルド失敗時に考えられる3つの理由_1
    「Player Settings」をクリックしてください。

    【Android】IL2CPPビルド失敗時に考えられる3つの理由_2
    Scripting Backendを「IL2CPP」にします。 そして64bit版アプリを書き出す場合はTarget Architecturesの 「ARM64」 にチェックを入れましょう。
    ※Monoビルドの場合は、ARM64(64bitアプリ)は選べません

    以上の設定でビルドするとIL2CPPを使った64bit版のアプリが完成します。

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

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

    【Android】IL2CPPビルド失敗時に考えられる3つの理由_3
    ちなみにアプリのビルドは メニューFile > Build Profiles からBuild Profilesウィンドウを開きます。

    【Android】IL2CPPビルド失敗時に考えられる3つの理由_4
    「Build」または「Build And Run」ボタンを押すだけです。

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

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

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

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

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

    ②シンボル設定ミス

    ③NDKが未インストール

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

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

    日本人ならではの問題かもしれませんが、最もハマりやすい原因がこれ 「Unityプロジェクトのパスに日本語名が含まれている」 です。

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

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

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

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

    【Android】IL2CPPビルド失敗時に考えられる3つの理由_5
    ちなみにUnity6000.0.32f1でテストした際はビルド時に上図のような 「Invalid project path」 というダイアログが表示されます。 「日本語が含まれていてパスが不正」 という意味です。

    Unityエディタのバージョンアップによってビルドエラー内容も分かりやすくなりました。

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

    直し方は簡単です。パス内の日本語を半角英数に変更するだけ。上記の例では「てすと」を「test」に変更しました。

    これでビルドが成功するようになります。

    プロジェクトパス変更時は要注意

    IL2CPPビルドエラーを直すために、さらっとUnityプロジェクトのパスを変更しましたが 注意 しながら進めてください。

    まず Unityエディタで開いているなら閉じましょう。 トラブルの元です。

    そしてUnityプロジェクトのパスを変更するとUnity Hub内のパスが通らなくなり起動できなくなります。

    【Android】IL2CPPビルド失敗時に考えられる3つの理由_6
    パスを変更したUnityプロジェクトは、Unity Hubの 「開くボタン」 から再度Unity Hubに登録してみてください。

    すると以前のようにUnity HubからUnityプロジェクトが開くようになります。

    【Android】IL2CPPビルド失敗時に考えられる3つの理由_7
    また不要になったプロジェクトは 「リストからプロジェクトを削除」 をクリックして削除可能です。

    ビルドログから日本語がよくない理由がわかる

    少し余談ですがエラーログを読むことでなぜ日本語が良くないのかが分かります。

    IL2CPPビルドに失敗したときのエラーログをConsoleウィンドウから見てみましょう。次のエラーは所定のパスのファイルを参照できずにエラーを起こしていることが読み取れます。
    【Android】IL2CPPビルド失敗時に考えられる3つの理由_8
    パスの中で「???」が怪しいですよね。実はここには 日本語 が入っていたのです。

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

    Assetsフォルダ内のファイルに日本語を使うことは問題なし

    ちなみに、UnityプロジェクトのAssetsフォルダ配下の日本語名ファイルはどうなのでしょうか。
    【Android】IL2CPPビルド失敗時に考えられる3つの理由_9
    ↑上図のようにAssetsフォルダ内の日本語ファイルは、結論ビルドに問題は出ません。

    ただし、よっぽどの理由がない限りファイル名に日本語は使わない方がよいです。プログラミングにおいて日本語はトラブルの元。

    その②シンボル定義ミス

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

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

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

    上記のような感じで処理を分岐できるのです。特によく使われるのはネイティブプラグインです。ネイティブプラグインとはプラットフォームごとの独自の機能にアクセスする機能です。C#だけではなくJava、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_();  
    
    【修正後】ビルド成功
    // Androidビルドでは不要なのでシンボルで囲む  
    #if UNITY_IOS
        [DllImport("__Internal")]  
        private static extern string Hoge_();  
    #endif
    

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

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

    その③NDKが未インストール

    Androidビルドに必要なビルドサポートモジュールにNDKがあります。NDKとは「Native Development Kit」、つまりネイティブ機能を開発するために必要なツールです。

    Monoビルド自体はNDKは不要でした。なぜならネイティブコードを事前に作成することなくILのまま動作していたからです。

    しかしIL2CPPビルドははネイティブコードを生成する必要があるため NDKが必要になった ということです。

    詳しくはこちらの記事を参考にNDKをインストールしてみてください。

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

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

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

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

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

    ③NDKが未インストール

    こんな感じです。

    ビルドして実機確認はゲーム開発中の必須作業です。Unityエディタ上でいくら完璧でも実機で確認していないのであれば、それはアプリとしてはスタート地点にすら立っていない状態だと思っています。

    • 実機で確認するとなぜかエラーが起きる
    • そもそもビルドできない
    • 実機だと負荷が高すぎて重い
    • 特定の端末で描画が崩れる
    • 特定端末でクラッシュ

    などなど。実機で確認するといろんな課題が見えてきます。現状を確認することがアプリ完成において非常に重要です。

    もしIL2CPPビルドエラーで困っている方はこの記事を参考に直して実機確認をしてみましょう。いろんな発見があるかもしれません。

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

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