
Unity2018.1からのBuildPlayerを試す
Unity 2018.1より、BuildPipeline.BuildPlayerのAPIが更新されました。
この記事ではその変更内容と、実際に導入してみて少しハマった事例について紹介したいと思います。
APIの変更点
Unity 2017.xまでは、BuildPipeline.BuildPlayer
の戻り値はstringでした。
この戻り値はそのビルドでエラーが発生した際に、そのエラー内容を 文字列 で返却します。
Unity2018.1からはこの戻り値がstring
ではなく、Build.Reporting.BuildReportを返却するようになりました。
Build.Reporting.BuildReport
とは
Build.Reporting.BuildReport
は文字通り、Unityのビルドプロセスの結果を保持するクラスです。
結果クラスを返してくれることで、ビルド時にどういう過程がありどの程度時間がかかったのか、どういう箇所でエラーが発生したのかなど、ビルドの詳細を把握しやすくなりました。
このクラスの保持するデータについて、説明していきます。
BuildReport.summary
文字通り、ビルド結果の概要を保持するクラスになります。 よく使いそうな変数を列挙します。
変数名 | 説明 |
---|---|
result |
ビルド結果をBuildResultで保持します |
totalErrors |
ビルドの総エラー数を保持します |
totalWarnings |
ビルドの総警告数を保持します |
totalSize |
ビルド成果物のサイズをbytesで保持します |
totalTime |
ビルドの総時間をSystem.TimeSpan で保持します |
ビルドそのものが成功したかどうかは、result
変数を介して取得することができます。
後述しますが、ビルドが失敗したときには、いままでは例外を投げていたのですが、2018.1からは例外を投げなくなったので、result
変数をみてエラーハンドリングをする必要があります。
また、警告やエラー数・ビルド成果物のサイズを取得できるようになったため、Jenkinsなどでビルドしたときのビルドの統計情報を作成が楽になりました。
BuildReport.steps
ビルドの各ステップの情報を配列で保持しています。
変数名 | 説明 |
---|---|
name |
ビルドステップの名前を保持します |
depth |
ビルドステップのネストの深さを保持します |
duration |
そのステップに要した時間を秒単位で保持します |
messages |
そのステップでのログの一覧を保持します。各メッセージは、ログの種類(Warning, Errorなど)と実際のメッセージを保持します |
name
やduration
によって、各ビルドにはどういう工程が存在し、それらがどの程度時間がかかっているかがわかるようになったため、
例えば、ビルド時間の改善の手がかりなどにうまく利用できるのではないのかなと思います。
また、各ビルドステップごとにログを吐いてくれるのも嬉しところです。
ちなみに実験的ではありますが、ビルドステップに Compile scripts
という工程がありますが、プロジェクトで記述したスクリプトの警告ログもここに吐くようです。
こちらのログを収集して、例えばJenkinsでCIをしているなら通知することで、プロジェクトの品質維持に効果的かもしれません。
BuildReport.files
ビルドプロセスで生成されたファイル情報が配列で保持されています。
変数名 | 説明 |
---|---|
path |
生成されたファイルの絶対パスを保持します |
role |
生成されたファイルの役割を保持します |
size |
ファイルサイズをbyte形式で保持します |
実験的ではありますが、具体的に、空のサンプルプロジェクトのiOSビルドした際には、以下のような情報が取得できました。
BuildFile path: /path-to-project/Temp/StagingArea/Data/Managed/UnityEngine.UI.dll
BuildFile role: ManagedLibrary
BuildFile size: 250368
BuildFile path: /path-to-project/Temp/StagingArea/Data/Managed/UnityEngine.Networking.dll
BuildFile role: ManagedLibrary
BuildFile size: 255488
BuildFile path: /path-to-project/Temp/StagingArea/Data/Managed/UnityEngine.Timeline.dll
BuildFile role: ManagedLibrary
BuildFile size: 92672
BuildFile path: /path-to-project/Temp/StagingArea/Data/Managed/UnityEngine.SpatialTracking.dll
BuildFile role: ManagedLibrary
BuildFile size: 9216
BuildFile path: /path-to-project/Temp/StagingArea/Data/globalgamemanagers
BuildFile role: GlobalGameManagers
BuildFile size: 28776
BuildFile path: /path-to-project/Temp/StagingArea/Data/level0
BuildFile role: Scene
BuildFile size: 5281
BuildFile path: /path-to-project/Temp/StagingArea/Data/globalgamemanagers.assets
BuildFile role: SharedAssets
BuildFile size: 24908
BuildFile path: /path-to-project/Temp/StagingArea/Data/sharedassets0.assets
BuildFile role: SharedAssets
BuildFile size: 21160
BuildFile path: /path-to-project/Temp/StagingArea/Data/Resources/unity_builtin_extra
BuildFile role: BuiltInShaders
BuildFile size: 638968
BuildFile path: /path-to-project/Temp/StagingArea/Data/boot.config
BuildFile role: BootConfig
BuildFile size: 55
BuildFile path: /path-to-project/Temp/StagingArea/Data/unity default resources
BuildFile role: Unity default resources
BuildFile size: 6133660
BuildFile path: /path-to-project/Temp/StagingArea/Data/Managed/mono/2.0/machine.config
BuildFile role: Mono 2.0 machine.config
BuildFile size: 27625
BuildFile path: /path-to-project/Temp/StagingArea/Data/Managed/mono/4.0/machine.config
BuildFile role: Mono 4.0 machine.config
BuildFile size: 33648
BuildFile path: /path-to-project/iOSBuild/Libraries/libiPhone-lib.a
BuildFile role: Unity Player static library
BuildFile size: 539456888
BuildFile path: /path-to-project/iOSBuild/Libraries/libil2cpp.a
BuildFile role: IL2CPP static library
BuildFile size: 97469512
BuildReport.strippingInfo
このビルドに含まれているUnityEngineのネイティブコードモジュールの一覧と、その理由に関する情報を保持します。
この変数は、そのビルド対象のプラットフォームがcode stripping
をサポートするプラットフォームであるときのみ利用できます。
サポートしない場合は、null
が代入されます。
含まれているネイティブコードモジュールの一覧を取得するためには、BuildReport.strippingInfo.includedModules
プロパティを参照します。
そのモジュールがなぜ含まれているのかを知るには、BuildReport.strippingInfo.GetReasonsForIncluding
に、モジュール名を引数で渡すことで取得できます。
エラーハンドリングの変更点
いままでBuildPipeline.BuildPlayer
は、ビルド中にエラーが発生すると、例外を投げる実装になっていましたが、
Unity 2018.1からは、ビルド成功有無にかかわらず、例外を投げないようになりました。
Unityをバッチモードで起動した場合の戻り値は、例外を投げた場合には1
、EditorApplication.Exit
を実行した場合は、
そのExit
の引数がそのまま戻り値に、それ以外の場合は0
、つまり成功という扱いになります(参考: -executeMethod)
そのため例えば下記のように、単純にBuildPipeline.BuildPlayer
を実行するだけでは、ビルドが失敗した場合でも成功扱いになってしまいます。
using UnityEditor;
using UnityEngine;
// 引用: https://docs.unity3d.com/2018.1/Documentation/ScriptReference/BuildPipeline.BuildPlayer.html
public class BuildPlayerExample : MonoBehaviour
{
public static void MyBuild()
{
BuildPlayerOptions buildPlayerOptions = new BuildPlayerOptions();
buildPlayerOptions.scenes = new[] { "Assets/Scene1.unity", "Assets/Scene2.unity" };
buildPlayerOptions.locationPathName = "iOSBuild";
buildPlayerOptions.target = BuildTarget.iOS;
buildPlayerOptions.options = BuildOptions.None;
BuildPipeline.BuildPlayer(buildPlayerOptions);
}
}
# 下記のコマンドが、戻り値0となる
# 例えばJenkinsビルドで、戻り値が非0で失敗するように組んでいると
# 失敗していようが成功扱いとしてしまう
/Path/To/Unity -batchmode -executeMethod BuildPlayerExample.MyBuild -buildTarget iOS
一方今回の変更で、ビルド情報がBuild.Reporting.BuildReport
に含まれるようになりました。
適切にエラーハンドリングを行うためには、BuildReport.summary.result
を見てやる必要があります。
下記に実装例を記載します。
#if UNITY_EDITOR
using UnityEditor;
using UnityEditor.Build.Reporting;
using UnityEngine;
using System.Text;
// 引用: https://docs.unity3d.com/2018.1/Documentation/ScriptReference/BuildPipeline.BuildPlayer.html
public class Builder : MonoBehaviour
{
public static void MyBuild()
{
BuildPlayerOptions buildPlayerOptions = new BuildPlayerOptions();
buildPlayerOptions.scenes = new[] { "Assets/Scenes/Scene1.unity" };
buildPlayerOptions.locationPathName = "iOSBuild";
buildPlayerOptions.target = BuildTarget.iOS;
buildPlayerOptions.options = BuildOptions.None;
BuildReport buildReport = BuildPipeline.BuildPlayer(buildPlayerOptions);
// // buildReport.resultを見て、戻り値を決定する
if (buildReport.summary.result == BuildResult.Succeeded)
{
const int kSuccessCode = 0;
EditorApplication.Exit(kSuccessCode);
}
else
{
const int kErrorCode = 1;
EditorApplication.Exit(kErrorCode);
}
}
}
#endif
まとめ
Unity 2018.1におけるBuildPipeline.BuildPlayer
についての変更点と、変更に合わせてハマった点について紹介しました。
もともとのBuildPipeline.BuildPlayer
は返す情報がstring
だけだったので、おそらく多くの開発者がEditor.log
などを解析して、CIでの情報を充実させることが多かったと思うので、この変更は良いなと感じました。
この記事へのコメントはありません。