2022年5月24日火曜日

Unreal Engine 5でAndroidパッケージ作成 on MacBook Pro M1

MacBook Pro M1上のUnreal Engine 5でAndroid用パッケージ(apk)を作成する環境を構築した。
その時に発生したエラーと対処法について。
※最後に詳細を書いてますが、エラー②についてはWindowsユーザの方も参考になるかも知れません。

【環境】
MacBook Pro M1 Pro (2021年モデル) macOS Monterey
Unreal Engine 5.0.1
Android Studio Chipmunk | 2021.2.1 ※Android Studio Bumblebeeでも同じだと思う。

【経緯及びエラー内容】
Unreal Engineの以下のページを参照すると、「Android Studio version 4.0」とか古いAndroid Studioしか正式には対応してなさそう。

実際には、最新の「Android Studio Chipmunk」でもできたのだが、
正式手順ではないため、あくまでも自己責任でお願いします。

環境的には、Android Studio Chipmunkインストール済みの環境で、FlutterでAndroidアプリ開発を行なって、アプリをGoogle Play Storeにリリースまでしている環境。つまりそれまではUnreal Engineは入れてなかった環境にUnreal Engine 5 を入れた状態。(なのでAndroid Studio version 4.0とか古いものは入れたくなかった。)

よって、上記リンクで言うところの
1.Android Studio をインストールする
2. Android Studio を設定する (初回ユーザーの場合)
※2.10 Android SDK Command-line Tools についてもインストール済みだった。
はスキップして、
3. Setting Up Android NDK
から実行。
なお、mac上のSetupAndroid スクリプトの場所は以下。
/Users/Shared/Epic Games/UE_5.0/Engine/Extras/Android/SetupAndroid.command

【エラー①】
SetupAndroid.command  67行目あたりで、JAVA_HOMEを設定しているが、これがAndroid Studio 4の古い設定(Java 1.8用)になっている。新しいAndroid StudioだとJava 11。
export JAVA_HOME="$STUDIO_PATH/Contents/jre/jdk/Contents/Home"

対策①: 新しいAndroid Studioの付属jdkを既にJAVA_HOME環境設定に設定済みの場合
つまりprintenvで以下の結果になる場合
> printenv |grep JAVA_HOME
JAVA_HOME=/Applications/Android Studio.app/Contents/jre/Contents/Home

この場合は、単純にSetupAndroid.commandのexport JAVA_HOMEをコメントアウトすれば良い。
export JAVA_HOME="$STUDIO_PATH/Contents/jre/jdk/Contents/Home"
# export JAVA_HOME="$STUDIO_PATH/Contents/jre/jdk/Contents/Home"

対策②: JAVA_HOME環境変数が未設定の場合
この場合は、SetupAndroid.commandのexport JAVA_HOMEのパスを修正すればよい。
export JAVA_HOME="$STUDIO_PATH/Contents/jre/jdk/Contents/Home"
↓
export JAVA_HOME="$STUDIO_PATH/Contents/jre/Contents/Home"

※なお、SetupAndroid.commandを実行すると、
SetupAndroid.command: line 20: rem: command not found
が出力され、実際にスクリプトを見てみると確かにrem、つまりDOSコマンドの「コメントアウト」キーワードが使用されている^^ しかしエラーで止まるわけでもなくスルーされるだけなので気にしなくて大丈夫(後でEpicに教えるだけ教えておこう^^ Unreal Engine 4.x の頃からこのままだっただろうし、ずっと放置されてきたのだろうから、Mac + Unreal Engine + Android開発はものすごくマイナーなのだと、逆に知ることができるのである^^)

P.S. 2022.10
Unreal Engine 5.1.0 (現時点ではPreview版) にて、上記remは修正されました!よかったよかった👍
rem hardcoded versions for compatibility with non-Turnkey manual running
↓
# hardcoded versions for compatibility with non-Turnkey manual running


【エラー②】
上記修正をして、再度SetupAndroid.commandを実行すると今度は以下のエラーが発生。
Exception in thread "main" java.lang.NoClassDefFoundError: javax/xml/bind/annotation/XmlSchema

色々調べたところ以下のようにSetupAndroid.commandを修正すればよかった。
(83行目あたり) 
(修正前)
SDKMANAGERPATH="$STUDIO_SDK_PATH/tools/bin"
if [ ! -d "$SDKMANAGERPATH" ]; then
        SDKMANAGERPATH="$STUDIO_SDK_PATH/cmdline-tools/latest/bin"
        if [ ! -d "$SDKMANAGERPATH" ]; then
                echo Unable to locate sdkmanager. Did you run Android Studio and install cmdline-tools after installing?
                ${PAUSE}
                exit 1
        fi
fi

↓
(修正後)
#SDKMANAGERPATH="$STUDIO_SDK_PATH/tools/bin"
#if [ ! -d "$SDKMANAGERPATH" ]; then
        SDKMANAGERPATH="$STUDIO_SDK_PATH/cmdline-tools/latest/bin"
        if [ ! -d "$SDKMANAGERPATH" ]; then
                echo Unable to locate sdkmanager. Did you run Android Studio and install cmdline-tools after installing?
                ${PAUSE}
                exit 1
        fi
#fi

つまり、使用するsdkmanagerが違っていた問題。(これもJava 8 → 11 問題か)
$STUDIO_SDK_PATH/tools/binの方をコメントアウトして、追加で入れたCommand Line Toolsの方を使うように修正すればエラー発生しなくなった。

ーーー
エラー①のJAVA_HOMEについては、Windows用とMac用とで、JAVA_HOME環境変数の判定処理が異なっている。
Windows用(SetupAndroid.bat): 最初にJAVA_HOME環境変数が定義されてるかチェック
Mac用(SetupAndroid.command): 最初に強制的にJAVA_HOME環境変数を定義(export)

ただし、エラー②については、Windows用とMac用とで同じ処理内容だったため、エラー②の問題についてはWindowsユーザの方も参考になるかも知れない。
ーーー

【エラー③】
これで再度Unreal Engine 5 でAndroidのパッケージ作成( Platforms → Android → Package Project)を行うと、最後のapk作成部分で以下のエラーが発生する。
…
Making .apk with Gradle...
To honour the JVM settings for this build a new JVM will be forked. Please consider using the daemon: https://docs.gradle.org/6.1.1/userguide/gradle_daemon.html.
Daemon will be stopped at the end of the build stopping after processing

FAILURE: Build failed with an exception.

* Where:
Settings file '/プロジェクトフォルダ/Intermediate/Android/arm64/gradle/settings.gradle' line: 9

* What went wrong:
A problem occurred evaluating settings 'app'.
> AFSProject/gradle.properties (No such file or directory)

* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.

* Get more help at https://help.gradle.org

対応方法としては、上記* Where: に書かれているsettings.gradleファイルをエディタで開き、以下の修正をしてファイルを保存する。
new File('xxx')
↓
file('xxx')

※「new F」を「f」に置換すると簡単。
settings.gradleファイルでは「new File('xxx')」を使ってる箇所が8箇所あるので、8箇所とも修正する。

※Unreal Engineしか知らない人からすると「Gradle」が突然出てきて「何だそれは?」と思われるかもしれないが、AndroidとかJavaとか開発してる人からすると日常的にお世話になっているシロモノ。AndroidとかJavaに詳しい人に聞いてみましょう。

エラー内容としては、gradleで「new File('xxx')」の書き方をすると、ビルドフォルダからの相対パスではなく、gradleデーモンのワーキングディレクトリからのパスと解釈されてしまうらしく、よって「AFSProject」という親フォルダが存在しないので、「gradle.properties」ファイルも作成できませんよ、というエラー。
なお、gradleデーモンのワーキングディレクトリ及び実際に作ろうとしてたファイルパスは私の環境では以下だった。
/Users/user_x/.gradle/daemon/6.1.1/AFSProject/gradle.properties
よってこれを「file('xxx')」関数にしてあげれば、ビルドフォルダからの相対パスとして正常処理できるようになる。
※ただしこれもgradleというか、Android Studioに紐づいたgradleのバージョンの問題かも知れない。(流石に一度も動かないスクリプトを上げるわけないと思うのでAndroid Studio 4ではうまく行くのだろう。でもgradleバージョンによってnew File()の起点が変わるのは結構破壊的変更なので、gradleの環境周りとかもっと深い話かも知れない。要はその辺の微妙なところがバージョンの違いでうまく噛み合っていないっぽい。)

P.S. Gradleリファレンスで以下を見つけた。

やはりnew File()だとCurrent Working Directory(CWD)からの相対パスになってるとのこと。そうすると、Android Studio 4 バージョンだった時の可能性としては以下があげられる。
可能性①: 以前のgradleバージョンではnew File()もfile()同様、ビルドフォルダからの相対パスになっていた。(つまりどこかでnew File()の破壊的変更があった。)
可能性②: gradleバージョン差異の影響で、change directory(cd)が処理されておらずCWDが変更されてなかった。(特にエラーも発生せずに)。またはgradleのchange directoryの解釈が変わったりしてCWDとしては変わっていなかった。
可能性③: やっぱりAndroid Studio 4でもこの箇所でエラーになる^^(つまり一度も動いてないスクリプトだった^^)

可能性は絞れたが、ここではそこまでは追わない。。



次の手順が注意が必要であるが、上記修正&保存をしたら、ターミナルを開いて自分でgradleを動かしてあげる必要がある。
理由:UE側でAndroidのパッケージ作成( Platforms → Android → Package Project)を行うと、修正したファイルが毎回上書き更新されてnew File('xxx')に戻ってしまうため。ちょっとだけ追ってみたところ、該当settings.gradleはUE側のスクリプトで生成しているようです。
> cd /プロジェクトフォルダ/Intermediate/Android/arm64/gradle/
> ./gradlew assembleDebug
「assembleDebug」はデバッグ用apkを作成するタスク(コマンド)。目的に合わせてタスクは変えて下さい。タスク一覧は「./gradlew :tasks」で確認可能。どのタスクを使うとかはAndroid Studioの話になってくるので、Android Studioリファレンスを参照して下さい。

これで無事にapkが作成できた!ただしapk出力パスはUnreal Engineで指定した場所ではなかったため注意。私の環境の場合は以下になっていた。
/プロジェクトフォルダ/Binaries/Android/test_app-arm64.apk
※apkの出力先が異なっているため、手動でgradlewを実行する時のパラメータが足りてないかも知れない。assembleDebugしか試してないが、Play Store用にApp Bundleを作成する場合は証明書が必要となるため、その辺のパラメータもUnreal Engine側で設定した値は正常に引き継がれないかも知れない。ということで、App Bundle作成時はもっと複雑な問題が出てくると思われる。gradlewの引数を含めた実行コマンドが不明なので何とも言えないが、Unreal Engine側で動的に渡している場合は、もう人の手で補えるレベルのものではないかも知れない。(最後に結論として書くが、素直にAndroid Studio version 4を別途入れた方が良いかも^^)

これで、Androidエミュレータとか実機Android端末をつないで、adbコマンドでインストールすれば実行可能!
> cd /プロジェクトフォルダ/Binaries/Android
> adb install test_app-arm64.apk
Performing Streamed Install
Success

※ちなみにUnreal Engineでデフォルト設定でAndroidアプリ作って動かした時に「No Google Play Store Key. No OBB found...」エラーが発生する問題があるのだが、それはまた別問題なので、各種Q/Aサイトをご参照ください。



私の場合は、Unreal Enginの以下の設定をして上記エラーが発生しなくなり、アプリ起動に成功した。
Project Settings
 Platforms
  Android
   Package game data inside .apk? : Yes/Checked
   Disable verify OBB on first start/update. : Yes/Checked
   Force small OBB files. : Yes/Checked

 Project
  Packaging
   Full Rebuild : Yes/Checked
上記変更後は、Unreal Engine側で再度Android Package Projectが必要。そうすると、settings.gradleは毎回上書きされてしまうため、再度settings.gradleでエラー発生するので、「new File()」を書き換えて、手動でgradle実行となる。

もう一つの注意点としては、「adb install」する前に対象Android端末からは一回アプリをアンインストールしておいた方が良い。
(私は最終的に色々試したapkで、上書きadb installだとダメだったが、アンインストール後に全く同じapkで「adb install」したら正常起動できた。なので、Unreal Engine側の設定で一体どの項目がクリティカルだったのかは不明。)

こちらが実際にAndroid端末で動作したテストアプリの画面キャプチャー。黄色いでかいキャラクターは世界的人気ゲーム「ROBLOX」の「NOOB(ヌーブ)」です^^一体何のゲームを作ろうとしてるのか?って感じですね。

という訳で、無事にMac + Unreal Engine 5.0 + Android Studio Chipmunk でAndroidアプリのパッケージ作成が出来たわけだが、こんなに煩雑なことをするのなら、素直にAndroid Studio version 4.0 を入れた方が手っ取り早そうである^^という結論に達した。
(おそらく)Unreal Engine側としても最新Android Studio対応はしてくれてる/念頭にはおいてくれてると思うので、最新Andorid Studio連携はそれを待っても良いかも知れない。(最初に載せたリンクも「Unreal 4.25 以降は」となっているが、まだUnreal Engine 5.0 専用のページはない。)

ーーー
P.S. 2022.10 再度リンク先ページを確認したところ「Unreal 4.25 以降は」の表記が消えていた。そして内容はAndroid Studio 4.0のままだった。つまりUnreal Engine 5.0 ではやはりAndroid Studio 4.0のまま据え置く結果になった模様。。「最新Andorid Studio連携を待ったほうが良いかも」と書いたがUE5では可能性が薄れ、当分先になりそうなので、諦めて公式リファレンス通りAndroid Studio 4.0 を使いましょう!^^
ーーー


「どうしてもAndroid Studio環境を汚したくない!」という方は参考にしていただければ幸いである。(Unreal Engine側でNDKとか入れるので影響は少なからずあるのだが。。)

あと何点か、Mac + Unreal のマイナスポイントを上げておく。
・そもそもWindows用にパッケージ作成できない(ですよね?ちょっと調べただけだけど。どうしてもDirect Xの壁があるからそりゃ無理なのかな?逆にWindows版Unrealだとios版が作れる?ので羨ましい。)
・Unreal Engineライブラリで使えるものが少ない。ほとんどWindows用ばかり。UE5リリース時に話題になってた映画Matrixの「Cityサンプル」も、Microsoftの音響システム「 Project Acoustics」 もWindows版だけとか。せっかく「いいな」と思ったものを見つけてもMacだと試せない。。MacではNatiteは対応されていないし対応予定もないので、Cityサンプルを試すのはやはり無理っぽい。
There is no Mac OS support for Nanite, nor is any likely in the future due to 
graphics API limitations.
(Google翻訳)
Nanite に対する Mac OS のサポートはありません。また、グラフィックス API の制限により、
今後もサポートされる可能性はありません。

NANITE FOR EDUCATORS AND STUDENTS より抜粋
※Mac環境&UE5.1 で影が以前より濃くなる現象に直面した。根本解決ではないが、とりあえずの回避策を見つけたので、こちらを参照。

ーーー
そして、こちらもそもそも話だが、ゲームを「遊ぶ」側としてもEpic Games StoreのゲームはWindows版ばかりである。

ということで、本格的にゲーム開発する人は当然Windowsマシンで開発するのだろう。
「Windowsのゲームを本格的に開発したいので、Macを買いました」という人がいたら「なんでそうなるの?」となるだろう。
ゲーム + Mac + Unreal はモバイルゲーム開発とか、またはMacが好きでMac用ゲームを作りたいとかのパターンが考えられる。しかしこれも現時点での私個人の主観でしかないし、最近ではモバイルからPCへの逆パターンもあったり、MacからWindowsとかの流れもなきにしもあらずだと思う(少なくともJavaのEclipseとかか始まり、今ではAndroid Studio然りUnityやUnreal Engine然りというように「IDE」はWin&Mac両対応が当たり前になっている)ため、これもまた自己責任でこの辺の動向はウォッチしていって自分に合ったやり方・環境を見つけてくれればと思います。
(会社とか組織規模で考えれば、会社内にWindowsマシンもある訳で最終的なapk(aab)出力はWindows環境でやれば良い訳で、別にMacでapk(aab)出力を出力することにこだわることはないのかも知れない^^
と、そこまで話が遡ってしまうと、今回の話も、またUnreal EngingeがMac用にもAndroidパッケージ出力方法(手順)を作っている意味も無くなってしまうので、私も含めて「それしかない環境」でやっている人もいる訳で、また大きく言えばプラットフォームの(純粋な意味での)垣根を越えるという点に寄与しているという点において、意味はあるのであろう。※「純粋な意味での垣根を越える」とは、お互いにWin-Win関係になれる、という意味。
ちょっと湾曲的すぎて何を言ってるのかわけがわからないと思うので、簡単にいうと「クリエーターからするとEpicとAppleの訴訟なんて知ったこっちゃなくて、せっかく素晴らしい3DCGエンジンがあるのだから、グラフィックとかアート分野に強いMacでも使わせて欲しい!」と言ったところだろう。それこそFortniteとかちゃちい話(失礼!)ではなく、Win-Winになれると思うのだが。。
かと言って、実際問題としてこのように影響があるのだから、訴訟の話も無視するわけにはいかず、話はぐるぐる回るわけである。。)