问题
- 我需要为项目中特定场景支持不同的构建设置(例如构建禁用硬件统计信息标志或删除自定义分析事件),并通过命令行或自动构建系统调用这些配置(例如Jenkins)。
- 我需要支持在iOS、Android、iOSTest、AndroidTest、WebGL或其他平台上自动构建我的游戏,并通过命令行调用它们与构建系统集成。
原因
Unity构建不同的玩家,但是为他们使用相似的全局配置。例如,如果项目使用PlayerSettings.SetScriptingDefineSymbolsForGroup 实现Custom Defines,您可能禁止这个功能,以便进行特定的测试,但是在生产构建的时候又需要激活它。Unity本身并不支持这个功能,所以您务必创建不同的构建脚本,以支持自定义设置。
解决方案
您可以借助Unity Cloud Build云构建实现该功能,它支持对不同场景下多种构建设置。欲了解更多信息,请参考Unity Cloud Build documentation.
您也可以创建某方法实现构建验证、更改设置和创建多种玩家。这些方法必须位于编辑器文件夹中的代码文件中,例如Assets/Editor/Builders/AndroidBuilder.cs。这个类不需要扩展任何Unity类 – 唯一的要求是使用静态函数。
例如,您想要Android、AndroidTest和iOS的三种构建,并使用控制命令行(或自动构建系统)去自动化地创建它们。如下所示,您可以建立两个脚本:: AndoidBuilder.cs (Assets/Editor/Builders/AndroidBuilder.cs) 和 iOSBuilder.cs (Assets/Editor/Builders/iOSBuilder.cs):
AndroidBuilder.cs:
using UnityEditor; class AndroidBuilder { static void ProductionBuild() { // ... your code here, validations, flag changes, etc. // Build the player.\ BuildPlayerOptions buildPlayerOptions = new BuildPlayerOptions(); buildPlayerOptions.scenes = new[] { "Assets/Scene1.unity", "Assets/Scene2.unity" }; buildPlayerOptions.locationPathName = "AndroidProdBuild"; buildPlayerOptions.target = BuildTarget.Android; buildPlayerOptions.options = BuildOptions.None; BuildPipeline.BuildPlayer(buildPlayerOptions); } static void TestBuild () { // ... your code here, validations, flag changes, etc. // Build the player.\ BuildPlayerOptions buildPlayerOptions = new BuildPlayerOptions(); buildPlayerOptions.scenes = new[] { "Assets/SceneTest1.unity", "Assets/SceneTest2.unity" }; buildPlayerOptions.locationPathName = "AndroidTestBuild"; buildPlayerOptions.target = BuildTarget.Android; buildPlayerOptions.options = BuildOptions.None; BuildPipeline.BuildPlayer(buildPlayerOptions); } }
iOSBuilder.cs:
using UnityEditor; class iOSBuilder { static void ProductionBuild() { // ... your code here, validations, flag changes, etc. // Build the player.\ BuildPlayerOptions buildPlayerOptions = new BuildPlayerOptions(); buildPlayerOptions.scenes = new[] { "Assets/Scene1.unity", "Assets/Scene2.unity" }; buildPlayerOptions.locationPathName = "iOSProdBuild"; buildPlayerOptions.target = BuildTarget.iOS; buildPlayerOptions.options = BuildOptions.None; BuildPipeline.BuildPlayer(buildPlayerOptions); } }
接下来,您可以使用下面的代码调用每个构建函数:
- /Path/To/Unity -quit -batchmode -executeMethod AndroidBuilder.ProductionBuild
- /Path/To/Unity -quit -batchmode -executeMethod AndroidBuilder.TestBuild
- /Path/To/Unity -quit -batchmode -executeMethod iOSBuilder.ProductionBuild
另一个方法是仅有一个构建脚本,通过命令行使用参数来选择应该建立哪个玩家。下面是一个例子:
Builder.cs:
using UnityEditor; using System; class Builder { static void iOSProductionBuild() { // ... your code here, validations, flag changes, etc. // Build the player.\ BuildPlayerOptions buildPlayerOptions = new BuildPlayerOptions(); buildPlayerOptions.scenes = new[] { "Assets/Scene1.unity", "Assets/Scene2.unity" }; buildPlayerOptions.locationPathName = "iOSProdBuild"; buildPlayerOptions.target = BuildTarget.iOS; buildPlayerOptions.options = BuildOptions.None; BuildPipeline.BuildPlayer(buildPlayerOptions); } static void AndroidProductionBuild() { // ... your code here, validations, flag changes, etc. // Build the player.\ BuildPlayerOptions buildPlayerOptions = new BuildPlayerOptions(); buildPlayerOptions.scenes = new[] { "Assets/Scene1.unity", "Assets/Scene2.unity" }; buildPlayerOptions.locationPathName = "AndroidProdBuild"; buildPlayerOptions.target = BuildTarget.Android; buildPlayerOptions.options = BuildOptions.None; BuildPipeline.BuildPlayer(buildPlayerOptions); } static void AndroidTestBuild() { // ... your code here, validations, flag changes, etc. // Build the player.\ BuildPlayerOptions buildPlayerOptions = new BuildPlayerOptions(); buildPlayerOptions.scenes = new[] { "Assets/SceneTest1.unity", "Assets/SceneTest2.unity" }; buildPlayerOptions.locationPathName = "AndroidTestBuild"; buildPlayerOptions.target = BuildTarget.Android; buildPlayerOptions.options = BuildOptions.None; BuildPipeline.BuildPlayer(buildPlayerOptions); } static void Build () { string[] arguments = Environment.GetCommandLineArgs(); switch ( arguments[1] ) { case "Android": AndroidProductionBuild(); break; case "AndroidTest": AndroidTestBuild(); break; case "iOS": iOSProductionBuild(); break; default: AndroidProductionBuild(); break; } } }
您可以使用下面的代码调用构建函数:
- /Path/To/Unity -quit -batchmode -executeMethod Builder.Build Android
- /Path/To/Unity -quit -batchmode -executeMethod Builder.Build AndroidTest
- /Path/To/Unity -quit -batchmode -executeMethod Builder.Build iOS
您可以通过使用其他参数(例如-target=Android|iOS -env=prod|dev)或自定义参数来扩展此方法。
您可以将这些方法和自动构建系统相结合,从而自动创建不同需求下的不同玩家,避免构建时的人为错误。
用这种方法,您可以实现下列自定义方法:
- 不同场景的开发构建。
- 使用PlayerSettings.SetScriptingDefineSymbolsForGroup自定义脚本#define指令。
- 包括/剔除插件。
- 包括/剔除特定场景。
- 编辑任何MyProject/ProjectSettings/*.asset下的资源文件(例如AudioManager.asset, GraphicsSettings.asset和ProjectSettings.asset)
- 使用C#脚本更新资源。
- 根据项目需求开启或关闭自定义插件(例如通过平台、渲染API或任何其他特定功能)。
- 在必要时,使用任何C#脚本。
更多信息
更多信息请参考以下文档:
- Command line arguments documentation
- BuildPipeline.BuildPlayer script reference documentation
- Microsoft Método Environment.GetCommandLineArgs () documentation
- Custom scripting #define directives documentation