エンジニアの岡村です。
Unityのアプリ開発をチームで行う際は、Git等のバージョン管理ツールがほぼ必ず使われます。これを使って他のメンバーとプロジェクトフォルダを共有するのですが、Unityをビルドする際に使われる設定の中にはプロジェクトフォルダの外に保存されるものがあります。
Editorの再生ボタンを叩いている間であれば問題になる事は少ないです。ですが、ビルドしたときの挙動を検証したい時など、作業者それぞれのPCでビルド設定が異なっていると正しく現象を再現できないことがあります。
また、CIで自動ビルドを行う際にも、ビルドマシン上でGUIを開き設定を変えなければなりませんし、普段確認できないために設定が変わっても気づかず、そうするといつの間にかおかしな状態に……という事もあります。これらの問題を解決するためにプロジェクト外に保存される設定も、少なくとも社内テスト版やリリース版に関しては設定内容のバージョン管理をしたくなります。
そこで、弊社のプロジェクトではそれらの設定をC#スクリプトから上書きすることにより、CIワークフローの一部としてプロジェクトフォルダ内で(コードとして)バージョン管理出来るようにしています。
プロジェクトフォルダに保存されない設定は、外部アプリケーションや実行環境に依存するようなものを除き、基本的にはBuild Settingsウィンドウに集約されています。このウィンドウはGUIベースで操作する分には幾分直感的なのですが、GUIの表記とC#のAPIが一致していなかったり名前空間が別の場所にあったり等、内部はかなりカオスになっています。公式ドキュメントもあまり詳しい情報が乗っていません。自分がBuild Settingsをコードから触ろうとした時には項目一つ一つについて調べる必要があった為そこそこ時間を取られました。
なので、今後自分や他の人が参考にするために、Build SettingsウィンドウとC#スクリプトの対応付けを今回テックブログの記事として紹介することにしました。
前提
環境はUnity 2021.3.0f1です。バージョンが前後するとBuild Settingsの内容も変化している可能性がありますのでご了承ください。
Build Settingsの多くの設定項目のAPIは EditorUserBuildSettings と BuildPlayerOptions に含まれています。それらのAPI呼び出しを以下の様なC#コードで記述し検証しました。
using System.Linq; using UnityEditor; using UnityEngine; public static class BuildScript { [MenuItem("Build/Windows")] public static void BuildWindows() { var buildPlayerOptions = new BuildPlayerOptions(); // ここにBuild Settingsの内容をコードで書く var report = BuildPipeline.BuildPlayer(buildPlayerOptions); Debug.Log(report.summary.result); } }
ビルドプラットフォームについて
Build Settingsウィンドウにはビルドターゲットのプラットフォーム指定をするUI(以下の画像における黄色の領域)があるのですが、ちょっと複雑なので事前に説明します。
ビルドプラットフォームの指定は、UIにおいてはPlatform, Target Platform, Architectureという表示になっていますが、それぞれBuildTargetGroup, BuildTarget, BuildSubtargetに(一部)対応しています。
それぞれ別のEnumの値を指定する必要があり、かなり複雑に見えますが、実際の所、中身はStandalone周りが多少パターンが多いくらいで、全体として有効な組み合わせの数は少なくなっています。
BuildTargetGroup | BuildTarget | BuildSubtarget |
---|---|---|
Unknown | ||
Standalone | StandaloneWindows | StandaloneBuildSubtarget.Player |
Standalone | StandaloneWindows | StandaloneBuildSubtarget.Server |
Standalone | StandaloneWindows64 | StandaloneBuildSubtarget.Player |
Standalone | StandaloneWindows64 | StandaloneBuildSubtarget.Server |
Standalone | StandaloneOSX | StandaloneBuildSubtarget.Player |
Standalone | StandaloneOSX | StandaloneBuildSubtarget.Server |
Standalone | StandaloneLinux64 | StandaloneBuildSubtarget.Player |
Standalone | StandaloneLinux64 | StandaloneBuildSubtarget.Server |
iOS | iOS | |
Android | Android | |
WebGL | WebGL | |
WSA | WSAPlayer | |
PS4 | PS4 | |
XboxOne | XboxOne | |
tvOS | tvOS | |
Switch | Switch | |
Stadia | Stadia | |
CloudRendering | CloudRendering | |
PS5 | PS5 |
C#で実際に指定する場合は以下のように書きます。
buildPlayerOptions.targetGroup = BuildTargetGroup.Standalone; buildPlayerOptions.target = BuildTarget.StandaloneWindows64; buildPlayerOptions.subtarget = (int)StandaloneBuildSubtarget.Player; // デフォルトがPlayerなので省略可能
また、NamedBuildTarget というenumを使ったプラットフォーム指定方法もありますが、こちらは後に紹介するコードでは使っていないため詳細は割愛します。Dedicated ServerへのSwitch Platformにはこれを使います。
EditorUserBuildSettings.SwitchActiveBuildTarget(NamedBuildTarget.Server, BuildTarget.StandaloneWindows64);
Architectureの指定について
WindowsのArchitectureはBuildTargetに含まれていますが、macOSでは指定方法が異なります。
Windows
buildPlayerOptions.target = BuildTarget.StandaloneWindows64;
macOS
#if UNITY_STANDALONE_OSX UnityEditor.OSXStandalone.UserBuildSettings.architecture = UnityEditor.OSXStandalone.MacOSArchitecture.x64ARM64; #endif
余談:ビルド時にプラットフォームを切り替えてもビルドスクリプト中の#if分岐は有効にならない
本筋とはあまり関係ありません。
前述のmacOSにおけるアーキテクチャの指定は、UnityEditorにmacOSビルド用のモジュールをインストールしていないとコンパイルエラーになってしまいます。UNITY_STANDALONE_OSX
シンボルが有効になっているならばmacOSプラットフォームにSwitch Platform済、つまりmacOSビルド用のモジュールがインストール済みであるので、これを特定プラットフォーム限定のビルド設定にアクセスする為の判定に使っています。しかし、ビルドスクリプト内でSwitch Platformを呼び出していると、ビルドスクリプト自身に対してシンボルの切り替えが反映されず、#ifで囲まれた部分がスキップされてしまうという問題をはらんでいます。
解決するにはコマンドライン引数の -buildTarget
を使い、最初からプラットフォームを指定して起動するか、SwitchPlatformを実行するだけのステップと、ビルドを行うステップに分けて、2回スクリプトを実行する等の対策が必要になります。
もしくは、もう一つの解決策として、SetPlatformSettingsを使うことで特定モジュールに依存せずにプラットフォーム限定の設定を行うことも可能ですが、こちらはどんなキーがありどんな値があるのかのドキュメントが存在しておらずあまり触れていません。一応以下の様に記述することでmacOSのアーキテクチャ指定が機能することは確認しています。
EditorUserBuildSettings.SetPlatformSettings("Standalone", "OSXUniversal", "Architecture", "x64");
Build Settings 一覧
本題のBuild SettingsとC#の対応一覧です。
Windows, Mac, Linux, (Dedicated Server), Android, iOS, WebGLの調査を行いました。スクリーンショットと比較して扱いやすいよう、かなり冗長に記載しています。また、外部のデバイスやプログラムに強く依存するような(手動でビルドするときに使うような)項目は調査していません。
ちなみに、Dedicated ServerのBuild SettingsはWindows, Mac, Linuxとの違いはありませんでした。
Windows
var buildPlayerOptions = new BuildPlayerOptions(); // Platform buildPlayerOptions.targetGroup = BuildTargetGroup.Standalone; buildPlayerOptions.subtarget = (int)StandaloneBuildSubtarget.Player; // Target Platform & Architecture buildPlayerOptions.target = BuildTarget.StandaloneWindows; buildPlayerOptions.target = BuildTarget.StandaloneWindows64; #if UNITY_STANDALONE_WIN // Copy PDB files UnityEditor.WindowsStandalone.UserBuildSettings.copyPDBFiles = false; // Create Visual Studio Solution UnityEditor.WindowsStandalone.UserBuildSettings.createSolution = false; #endif // Development Build buildPlayerOptions.options |= BuildOptions.Development; // Autoconnect Profiler buildPlayerOptions.options |= BuildOptions.ConnectWithProfiler; // Deep Profiling buildPlayerOptions.options |= BuildOptions.EnableDeepProfilingSupport; // Script Debugging buildPlayerOptions.options |= BuildOptions.AllowDebugging; // IL2CPP Code Generation = Faster runtime EditorUserBuildSettings.il2CppCodeGeneration = Il2CppCodeGeneration.OptimizeSpeed; // IL2CPP Code Generation = Faster (smaller) builds EditorUserBuildSettings.il2CppCodeGeneration = Il2CppCodeGeneration.OptimizeSize; // Compression Method = LZ4 buildPlayerOptions.options |= BuildOptions.CompressWithLz4; // Compression Method = LZ4HC buildPlayerOptions.options |= BuildOptions.CompressWithLz4HC; // createSolution=trueの場合は拡張子に.slnを指定する buildPlayerOptions.locationPathName = "Builds/Build.exe"; var report = BuildPipeline.BuildPlayer(buildPlayerOptions); Debug.Log(report.summary.result);
macOS
var buildPlayerOptions = new BuildPlayerOptions(); // Platform buildPlayerOptions.targetGroup = BuildTargetGroup.Standalone; buildPlayerOptions.subtarget = (int)StandaloneBuildSubtarget.Player; // Target Platform buildPlayerOptions.target = BuildTarget.StandaloneOSX; #if UNITY_STANDALONE_OSX // Architecture UnityEditor.OSXStandalone.UserBuildSettings.architecture = UnityEditor.OSXStandalone.MacOSArchitecture.x64ARM64; // Create Xcode Project UnityEditor.OSXStandalone.UserBuildSettings.createXcodeProject = false; #endif // Development Build buildPlayerOptions.options |= BuildOptions.Development; // Autoconnect Profiler buildPlayerOptions.options |= BuildOptions.ConnectWithProfiler; // Deep Profiling buildPlayerOptions.options |= BuildOptions.EnableDeepProfilingSupport; // Script Debugging buildPlayerOptions.options |= BuildOptions.AllowDebugging; // IL2CPP Code Generation = Faster runtime EditorUserBuildSettings.il2CppCodeGeneration = Il2CppCodeGeneration.OptimizeSpeed; // IL2CPP Code Generation = Faster (smaller) builds EditorUserBuildSettings.il2CppCodeGeneration = Il2CppCodeGeneration.OptimizeSize; // Compression Method = LZ4 buildPlayerOptions.options |= BuildOptions.CompressWithLz4; // Compression Method = LZ4HC buildPlayerOptions.options |= BuildOptions.CompressWithLz4HC; // createXcodeProject=trueにした場合は拡張子に.xcodeprojを指定する buildPlayerOptions.locationPathName = "Builds/Build.app"; var report = BuildPipeline.BuildPlayer(buildPlayerOptions); Debug.Log(report.summary.result);
Linux
var buildPlayerOptions = new BuildPlayerOptions(); // Platform buildPlayerOptions.targetGroup = BuildTargetGroup.Standalone; buildPlayerOptions.subtarget = (int)StandaloneBuildSubtarget.Player; // Target Platform buildPlayerOptions.target = BuildTarget.StandaloneLinux64; // Development Build buildPlayerOptions.options |= BuildOptions.Development; // Autoconnect Profiler buildPlayerOptions.options |= BuildOptions.ConnectWithProfiler; // Deep Profiling buildPlayerOptions.options |= BuildOptions.EnableDeepProfilingSupport; // Script Debugging buildPlayerOptions.options |= BuildOptions.AllowDebugging; // IL2CPP Code Generation = Faster runtime EditorUserBuildSettings.il2CppCodeGeneration = Il2CppCodeGeneration.OptimizeSpeed; // IL2CPP Code Generation = Faster (smaller) builds EditorUserBuildSettings.il2CppCodeGeneration = Il2CppCodeGeneration.OptimizeSize; // Compression Method = LZ4 buildPlayerOptions.options |= BuildOptions.CompressWithLz4; // Compression Method = LZ4HC buildPlayerOptions.options |= BuildOptions.CompressWithLz4HC; buildPlayerOptions.locationPathName = "Builds/Build.x86_64"; var report = BuildPipeline.BuildPlayer(buildPlayerOptions); Debug.Log(report.summary.result);
Android
var buildPlayerOptions = new BuildPlayerOptions(); // Platform buildPlayerOptions.targetGroup = BuildTargetGroup.Android; buildPlayerOptions.target = BuildTarget.Android; // Texture Compression = Use Player Settings EditorUserBuildSettings.androidBuildSubtarget = MobileTextureSubtarget.Generic; // ETC2 fallback EditorUserBuildSettings.androidETC2Fallback = AndroidETC2Fallback.Quality32Bit; // Export Project EditorUserBuildSettings.exportAsGoogleAndroidProject = false; // Symlink Sources EditorUserBuildSettings.symlinkSources = false; // Build App Bundle (Google Play) EditorUserBuildSettings.buildAppBundle = true; // Create symbols.zip EditorUserBuildSettings.androidCreateSymbols = AndroidCreateSymbols.Disabled; // Run Device及びBuild to Deviceは未調査 // Development Build buildPlayerOptions.options |= BuildOptions.Development; // Autoconnect Profiler buildPlayerOptions.options |= BuildOptions.ConnectWithProfiler; // Deep Profiling buildPlayerOptions.options |= BuildOptions.EnableDeepProfilingSupport; // Script Debugging buildPlayerOptions.options |= BuildOptions.AllowDebugging; // IL2CPP Code Generation = Faster runtime EditorUserBuildSettings.il2CppCodeGeneration = Il2CppCodeGeneration.OptimizeSpeed; // IL2CPP Code Generation = Faster (smaller) builds EditorUserBuildSettings.il2CppCodeGeneration = Il2CppCodeGeneration.OptimizeSize; // Compression Method = LZ4 buildPlayerOptions.options |= BuildOptions.CompressWithLz4; // Compression Method = LZ4HC buildPlayerOptions.options |= BuildOptions.CompressWithLz4HC; // buildAppBundle=trueにした場合は拡張子に.aabを指定する buildPlayerOptions.locationPathName = "Builds/Build.apk"; var report = BuildPipeline.BuildPlayer(buildPlayerOptions); Debug.Log(report.summary.result);
iOS
var buildPlayerOptions = new BuildPlayerOptions(); // Platform buildPlayerOptions.targetGroup = BuildTargetGroup.iOS; buildPlayerOptions.target = BuildTarget.iOS; // Run in Xcodeは未調査 // Run in Xcode as EditorUserBuildSettings.iOSXcodeBuildConfig = XcodeBuildConfig.Release; // Symlink Sources EditorUserBuildSettings.symlinkSources = false; // Development Build buildPlayerOptions.options |= BuildOptions.Development; // Autoconnect Profiler buildPlayerOptions.options |= BuildOptions.ConnectWithProfiler; // Deep Profiling buildPlayerOptions.options |= BuildOptions.EnableDeepProfilingSupport; // Script Debugging buildPlayerOptions.options |= BuildOptions.AllowDebugging; // IL2CPP Code Generation = Faster runtime EditorUserBuildSettings.il2CppCodeGeneration = Il2CppCodeGeneration.OptimizeSpeed; // IL2CPP Code Generation = Faster (smaller) builds EditorUserBuildSettings.il2CppCodeGeneration = Il2CppCodeGeneration.OptimizeSize; // Compression Method = LZ4 buildPlayerOptions.options |= BuildOptions.CompressWithLz4; // Compression Method = LZ4HC buildPlayerOptions.options |= BuildOptions.CompressWithLz4HC; buildPlayerOptions.locationPathName = "Builds/Build.xcodeproj"; var report = BuildPipeline.BuildPlayer(buildPlayerOptions); Debug.Log(report.summary.result);
WebGL
var buildPlayerOptions = new BuildPlayerOptions(); // Platform buildPlayerOptions.targetGroup = BuildTargetGroup.WebGL; buildPlayerOptions.target = BuildTarget.WebGL; // Texture Compression = Use default format(DXT) EditorUserBuildSettings.webGLBuildSubtarget = WebGLTextureSubtarget.Generic; // Development Build buildPlayerOptions.options |= BuildOptions.Development; #if UNITY_WEBGL // Code Optimization UnityEditor.WebGL.UserBuildSettings.codeOptimization = UnityEditor.WebGL.CodeOptimization.Speed; #endif // Autoconnect Profiler buildPlayerOptions.options |= BuildOptions.ConnectWithProfiler; // Deep Profiling buildPlayerOptions.options |= BuildOptions.EnableDeepProfilingSupport; // IL2CPP Code Generation = Faster runtime EditorUserBuildSettings.il2CppCodeGeneration = Il2CppCodeGeneration.OptimizeSpeed; // IL2CPP Code Generation = Faster (smaller) builds EditorUserBuildSettings.il2CppCodeGeneration = Il2CppCodeGeneration.OptimizeSize; buildPlayerOptions.locationPathName = "Builds/Build"; var report = BuildPipeline.BuildPlayer(buildPlayerOptions); Debug.Log(report.summary.result);
以上
以上の調査結果については、一応一通り叩いてはみていますが、社内のプロジェクトでは深く触っていない項目もある為、間違っている情報もあるかもしれません。何か気付いたところがあればタレコミをお願いします。