经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 软件/图像 » unity » 查看文章
Unity实现批量Build打包详解
来源:jb51  时间:2021/12/15 9:11:39  对本文有异议

一般来讲如果项目是PC或Android、IOS端不会有批量Build打包这样的需求,但如果项目是WebGL端可能会遇到这样的需求:不同场景打包成不同的包体,入口是前端在页面中布局的,点击链接打开相应的程序。依次手动打包比较繁琐而且需要等待很长时间,因此写了批量Build这样的功能,下班时点击Build经历漫长的夜晚,第二天上班时包体已经都打好了。

核心API是UnityEditor.BuildPipeline类中的BuildPlayer,调用该方法传入相应参数即可实现打包,我们要做的是做一个配置文件,在其中配置打包不同包体对应的数据,包含打包的场景、名称和平台等。首先构建可序列化类:

  1. /// <summary>
  2. /// 打包任务
  3. /// </summary>
  4. [Serializable]
  5. public sealed class BuildTask
  6. {
  7. /// <summary>
  8. /// 名称
  9. /// </summary>
  10. public string ProductName;
  11. /// <summary>
  12. /// 目标平台
  13. /// </summary>
  14. public BuildTarget BuildTarget;
  15. /// <summary>
  16. /// 打包路径
  17. /// </summary>
  18. public string BuildPath;
  19. /// <summary>
  20. /// 打包场景
  21. /// </summary>
  22. public List<SceneAsset> SceneAssets = new List<SceneAsset>(0);
  23. }

使用ScriptableObject构建配置:

  1. /// <summary>
  2. /// 打包配置表
  3. /// </summary>
  4. [CreateAssetMenu(fileName = "New Build Profile", menuName = "Build Profile")]
  5. public sealed class BuildProfile : ScriptableObject
  6. {
  7. /// <summary>
  8. /// 打包任务列表
  9. /// </summary>
  10. public List<BuildTask> BuildTasks = new List<BuildTask>(0);
  11. }

有了BuildProfile后,配置打包列表,批量打包要做的就是遍历该列表依次调用BuildPipeline中的BuildPlayer方法。创建Editor类,重写BuildProfile的Inspector面板,编写打包功能,以及添加、移除打包项等菜单。

  1. [CustomEditor(typeof(BuildProfile))]
  2. public sealed class BuildProfileInspector : Editor
  3. {
  4. private readonly Dictionary<BuildTask, bool> foldoutMap = new Dictionary<BuildTask, bool>();
  5. private Vector2 scroll = Vector2.zero;
  6. private BuildProfile profile;
  7. private void OnEnable()
  8. {
  9. profile = target as BuildProfile;
  10. }
  11. public override void OnInspectorGUI()
  12. {
  13. GUILayout.BeginHorizontal();
  14. {
  15. if (GUILayout.Button("新建", "ButtonLeft"))
  16. {
  17. Undo.RecordObject(profile, "Create");
  18. var task = new BuildTask()
  19. {
  20. ProductName = "Product Name",
  21. BuildTarget = BuildTarget.StandaloneWindows64,
  22. BuildPath = Directory.GetParent(Application.dataPath).FullName
  23. };
  24. profile.BuildTasks.Add(task);
  25. }
  26. if (GUILayout.Button("展开", "ButtonMid"))
  27. {
  28. for (int i = 0; i < profile.BuildTasks.Count; i++)
  29. {
  30. foldoutMap[profile.BuildTasks[i]] = true;
  31. }
  32. }
  33. if (GUILayout.Button("收缩", "ButtonMid"))
  34. {
  35. for (int i = 0; i < profile.BuildTasks.Count; i++)
  36. {
  37. foldoutMap[profile.BuildTasks[i]] = false;
  38. }
  39. }
  40. GUI.color = Color.yellow;
  41. if (GUILayout.Button("清空", "ButtonMid"))
  42. {
  43. Undo.RecordObject(profile, "Clear");
  44. if (EditorUtility.DisplayDialog("提醒", "是否确定清空列表?", "确定", "取消"))
  45. {
  46. profile.BuildTasks.Clear();
  47. }
  48. }
  49. GUI.color = Color.cyan;
  50. if (GUILayout.Button("打包", "ButtonRight"))
  51. {
  52. if (EditorUtility.DisplayDialog("提醒", "打包需要耗费一定时间,是否确定开始?", "确定", "取消"))
  53. {
  54. StringBuilder sb = new StringBuilder();
  55. sb.Append("打包报告:\r\n");
  56. for (int i = 0; i < profile.BuildTasks.Count; i++)
  57. {
  58. EditorUtility.DisplayProgressBar("Build", "Building...", i + 1 / profile.BuildTasks.Count);
  59. var task = profile.BuildTasks[i];
  60. List<EditorBuildSettingsScene> buildScenes = new List<EditorBuildSettingsScene>();
  61. for (int j = 0; j < task.SceneAssets.Count; j++)
  62. {
  63. var scenePath = AssetDatabase.GetAssetPath(task.SceneAssets[j]);
  64. if (!string.IsNullOrEmpty(scenePath))
  65. {
  66. buildScenes.Add(new EditorBuildSettingsScene(scenePath, true));
  67. }
  68. }
  69. string locationPathName = $"{task.BuildPath}/{task.ProductName}";
  70. var report = BuildPipeline.BuildPlayer(buildScenes.ToArray(), locationPathName, task.BuildTarget, BuildOptions.None);
  71. sb.Append($"[{task.ProductName}] 打包结果: {report.summary.result}\r\n");
  72. }
  73. EditorUtility.ClearProgressBar();
  74. Debug.Log(sb.ToString());
  75. }
  76. return;
  77. }
  78. GUI.color = Color.white;
  79. }
  80. GUILayout.EndHorizontal();
  81. scroll = GUILayout.BeginScrollView(scroll);
  82. {
  83. for (int i = 0; i < profile.BuildTasks.Count; i++)
  84. {
  85. var task = profile.BuildTasks[i];
  86. if (!foldoutMap.ContainsKey(task)) foldoutMap.Add(task, true);
  87. GUILayout.BeginHorizontal("Badge");
  88. GUILayout.Space(12);
  89. foldoutMap[task] = EditorGUILayout.Foldout(foldoutMap[task], $"{task.ProductName}", true);
  90. GUILayout.Label(string.Empty);
  91. if (GUILayout.Button(EditorGUIUtility.IconContent("TreeEditor.Trash"), "IconButton", GUILayout.Width(20)))
  92. {
  93. Undo.RecordObject(profile, "Delete Task");
  94. foldoutMap.Remove(task);
  95. profile.BuildTasks.Remove(task);
  96. break;
  97. }
  98. GUILayout.EndHorizontal();
  99. if (foldoutMap[task])
  100. {
  101. GUILayout.BeginVertical("Box");
  102. GUILayout.BeginHorizontal();
  103. GUILayout.Label("打包场景:", GUILayout.Width(70));
  104. if (GUILayout.Button(EditorGUIUtility.IconContent("Toolbar Plus More"), GUILayout.Width(28)))
  105. {
  106. task.SceneAssets.Add(null);
  107. }
  108. GUILayout.EndHorizontal();
  109. if (task.SceneAssets.Count > 0)
  110. {
  111. GUILayout.BeginHorizontal();
  112. GUILayout.Space(75);
  113. GUILayout.BeginVertical("Badge");
  114. for (int j = 0; j < task.SceneAssets.Count; j++)
  115. {
  116. var sceneAsset = task.SceneAssets[j];
  117. GUILayout.BeginHorizontal();
  118. GUILayout.Label($"{j + 1}.", GUILayout.Width(20));
  119. task.SceneAssets[j] = EditorGUILayout.ObjectField(sceneAsset, typeof(SceneAsset), false) as SceneAsset;
  120. if (GUILayout.Button("↑", "MiniButtonLeft", GUILayout.Width(20)))
  121. {
  122. if (j > 0)
  123. {
  124. Undo.RecordObject(profile, "Move Up Scene Assets");
  125. var temp = task.SceneAssets[j - 1];
  126. task.SceneAssets[j - 1] = sceneAsset;
  127. task.SceneAssets[j] = temp;
  128. }
  129. }
  130. if (GUILayout.Button("↓", "MiniButtonMid", GUILayout.Width(20)))
  131. {
  132. if (j < task.SceneAssets.Count - 1)
  133. {
  134. Undo.RecordObject(profile, "Move Down Scene Assets");
  135. var temp = task.SceneAssets[j + 1];
  136. task.SceneAssets[j + 1] = sceneAsset;
  137. task.SceneAssets[j] = temp;
  138. }
  139. }
  140. if (GUILayout.Button(EditorGUIUtility.IconContent("Toolbar Plus"), "MiniButtonMid", GUILayout.Width(20)))
  141. {
  142. Undo.RecordObject(profile, "Add Scene Assets");
  143. task.SceneAssets.Insert(j + 1, null);
  144. break;
  145. }
  146. if (GUILayout.Button(EditorGUIUtility.IconContent("Toolbar Minus"), "MiniButtonMid", GUILayout.Width(20)))
  147. {
  148. Undo.RecordObject(profile, "Delete Scene Assets");
  149. task.SceneAssets.RemoveAt(j);
  150. break;
  151. }
  152. GUILayout.EndHorizontal();
  153. }
  154. GUILayout.EndVertical();
  155. GUILayout.EndHorizontal();
  156. }
  157. GUILayout.BeginHorizontal();
  158. GUILayout.Label("产品名称:", GUILayout.Width(70));
  159. var newPN = GUILayout.TextField(task.ProductName);
  160. if (task.ProductName != newPN)
  161. {
  162. Undo.RecordObject(profile, "Product Name");
  163. task.ProductName = newPN;
  164. }
  165. GUILayout.EndHorizontal();
  166. GUILayout.BeginHorizontal();
  167. GUILayout.Label("打包平台:", GUILayout.Width(70));
  168. var newBT = (BuildTarget)EditorGUILayout.EnumPopup(task.BuildTarget);
  169. if (task.BuildTarget != newBT)
  170. {
  171. Undo.RecordObject(profile, "Build Target");
  172. task.BuildTarget = newBT;
  173. }
  174. GUILayout.EndHorizontal();
  175. GUILayout.BeginHorizontal();
  176. GUILayout.Label("打包路径:", GUILayout.Width(70));
  177. GUILayout.TextField(task.BuildPath);
  178. if (GUILayout.Button("Browse", GUILayout.Width(60)))
  179. {
  180. task.BuildPath = EditorUtility.SaveFolderPanel("Build Path", task.BuildPath, "");
  181. }
  182. GUILayout.EndHorizontal();
  183. GUILayout.EndVertical();
  184. }
  185. }
  186. }
  187. GUILayout.EndScrollView();
  188. serializedObject.ApplyModifiedProperties();
  189. if (GUI.changed) EditorUtility.SetDirty(profile);
  190. }
  191. }

到此这篇关于Unity实现批量Build打包详解的文章就介绍到这了,更多相关Unity批量Build打包内容请搜索w3xue以前的文章或继续浏览下面的相关文章希望大家以后多多支持w3xue!

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号