はじめに
普通の Unity プロジェクトの開発中は、以下のサイクルが何度も繰り返されることと思います。
- iOS 用の buildNumber をインクリメント
- iOS 用の Xcode プロジェクト書き出し
- iOS 用 ipa 作成
- ipa を fabric の beta で配布
- Android 用の bundleVersionCode をインクリメント
- Android 用 apk 書き出し
- apk を fabric の beta で配布
- slack で開発チームに報告
面倒ですね。fastlane でラクしましょう。
この記事は fastlane で Unity のビルドを行う部分を中心に書いていますので、fastlane の基本的な部分はこちらの記事などをどうぞ。
HOW?
1. ビルドスクリプトの準備
Assets/Editor 以下に、こんな感じでビルド用のスクリプトを配置します。
AppBuilder.cs
using UnityEditor;
using UnityEngine;
public class AppBuilder{
[MenuItem ("Build/Android向けビルド")]
static void buildForAndroid(){
bumpBuildNumberForAndroid ();
string errorMessage = BuildPipeline.BuildPlayer(GetAllScenePaths (), "/Users/plasticstraw/Desktop/game.apk", BuildTarget.Android, BuildOptions.None);
if( !string.IsNullOrEmpty( errorMessage ) )
Debug.LogError( "[Error!] " + errorMessage );
else
Debug.Log( "[Success!]" );
}
[MenuItem ("Build/iOS向けビルド")]
static void buildForIOS(){
bumpBuildNumberForIOS ();
// 出力パス。絶対パスで指定すること。また、最後にスラッシュを入れないこと。PostBuildProcess に渡る path が通常ビルドと異なってしまい、思わぬバグを引き起こすことがあります。
string path = "/Users/plasticstraw/Desktop/game";
string errorMessage = BuildPipeline.BuildPlayer(GetAllScenePaths(), path, BuildTarget.iOS, BuildOptions.Il2CPP);
if( !string.IsNullOrEmpty( errorMessage ) )
Debug.LogError( "[Error!] " + errorMessage );
else
Debug.Log( "[Success!]" );
}
static void bumpBuildNumberForIOS(){
string str = PlayerSettings.iOS.buildNumber;
int num = int.Parse (str);
num++;
PlayerSettings.iOS.buildNumber = num + "";
}
static void bumpBuildNumberForAndroid(){
PlayerSettings.Android.bundleVersionCode += 1;
}
static string[] GetAllScenePaths(){
string[] scenes = new string[EditorBuildSettings.scenes.Length];
for( int i = 0; i < EditorBuildSettings.scenes.Length ; i++ ) {
scenes[i] = EditorBuildSettings.scenes[i].path;
}
return scenes;
}
}
Unity のメニューに「Build 」が追加されているので、そこからそれぞれのビルド処理が期待通りに動くかテストできます。
2. Fastfile を記述
Unity には、コマンドラインから任意のスクリプトを実行する機能が備わっています。
fastlane を使って、上記で作成したビルドスクリプトを呼んでやることでビルドを自動化できます。
Fastfile
desc "ビルドして Beta で配布します。"
lane :beta do
buildForIOS
buildForAndroid
distributeByCrashlytics
slack(
default_payloads: [],
message: "<!channel>: Beta で配布したよ",
)
end
desc "iOS用ビルド"
lane :buildForIOS do
path = File.expand_path(File.dirname(__FILE__)) +"/../"
sh("/Applications/Unity/Unity.app/Contents/MacOS/Unity -batchmode -quit -logFile ./build.log -projectPath '#{path}' -buildTarget ios -executeMethod AppBuilder.buildForIOS")
gym(
project: "/Users/plasticstraw/Desktop/game/Unity-iPhone.xcodeproj",
)
end
desc "android用ビルド"
lane :buildForAndroid do
path = File.expand_path(File.dirname(__FILE__)) +"/../"
sh("/Applications/Unity/Unity.app/Contents/MacOS/Unity -batchmode -quit -logFile ./build.log -projectPath '#{path}' -buildTarget android -executeMethod AppBuilder.buildForAndroid")
end
desc "配布"
lane :distributeByCrashlytics do
# ios
crashlytics(
groups: 'team'
)
# android
crashlytics(
apk_path: "/Users/plasticstraw/Desktop/game.apk",
groups: 'team'
ipa_path: false, # デフォルトでiOSの値が入っており、apk_pathを指定しても正常に動作しないので値を削除
crashlytics_path: false, # デフォルトでiOSの値が入っており、android向けだと正常に動作しないため、値を削除してfastlaneに任せる
)
end
3.実行
あとはターミナルから $ fastlane beta
一発で、もろもろビルドしてもろもろ配布してくれます。おめでとうございます。
これを実行するためには Unity で該当のプロジェクトを開いている状態ではダメで、かつビルドで贅沢にCPUを食われるため、CIに組み込むなり、別のマシンでリポジトリをクローンしてから実行するなりがオススメです。