Unity多场景打包,多场景组合打包,单独打包,序列化打包
废话不多说,直接粘代码,代码一
这段代码是展示你想要修改包名了,LOGO了,版本号了等等乱七八糟的。新手别搞了,对新手不友好,代码点击单独打包按钮打包完成后会报错,我没解决,但是不影响使用,有大佬可以帮忙解决一下错误,我感觉是程序打包完成之后后边的GUI代码就不运行了。
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
/// <summary>
/// 打包任务
/// </summary>
[Serializable]
public sealed class BuildTask
{
/// <summary>
/// 默认图标
/// </summary>
public Texture2D DefaultIcon;
/// <summary>
/// 版本号
/// </summary>
public string Version;
/// <summary>
/// 包名,安卓平台用得到,Windows平台就可以直接注销了,相关连接的代码也都注销了即可
/// </summary>
public string PackageName;
/// <summary>
/// 名称
/// </summary>
public string ProductName;
/// <summary>
/// 目标平台
/// </summary>
public BuildTarget BuildTarget;
/// <summary>
/// 打包路径
/// </summary>
public string BuildPath;
/// <summary>
/// 打包场景
/// </summary>
public List<SceneAsset> SceneAssets = new List<SceneAsset>(0);
}
/// <summary>
/// 打包配置表
/// </summary>
[CreateAssetMenu(fileName = "New Build Profile", menuName = "Build Profile")]
public sealed class BuildProfile : ScriptableObject
{
/// <summary>
/// 打包任务列表
/// </summary>
public List<BuildTask> BuildTasks = new List<BuildTask>(0);
}
代码2
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Text;
using UnityEditor;
using UnityEngine;
[CustomEditor(typeof(BuildProfile))]
public sealed class BuildProfileInspector : Editor
{
private readonly Dictionary<BuildTask, bool> foldoutMap = new Dictionary<BuildTask, bool>();
private Vector2 scroll = Vector2.zero;
private BuildProfile profile;
private SerializedObject serializedProfile;
private SerializedProperty buildTasksProperty;
private void OnEnable()
{
profile = target as BuildProfile;
serializedProfile = new SerializedObject(profile);
buildTasksProperty = serializedProfile.FindProperty("BuildTasks");
serializedProfile.Update();
}
public override void OnInspectorGUI()
{
GUILayout.BeginHorizontal();
{
if (GUILayout.Button("新建", "ButtonLeft"))
{
Undo.RecordObject(profile, "Create");
var task = new BuildTask()
{
//preferb = null,
ProductName = "Product Name",
Version = "1.0.0.0",
BuildTarget = BuildTarget.Android,
BuildPath = Directory.GetParent(Application.dataPath).FullName
};
profile.BuildTasks.Add(task);
}
if (GUILayout.Button("展开", "ButtonMid"))
{
for (int i = 0; i < profile.BuildTasks.Count; i++)
{
foldoutMap[profile.BuildTasks[i]] = true;
}
}
if (GUILayout.Button("收缩", "ButtonMid"))
{
for (int i = 0; i < profile.BuildTasks.Count; i++)
{
foldoutMap[profile.BuildTasks[i]] = false;
}
}
GUI.color = Color.yellow;
if (GUILayout.Button("清空", "ButtonMid"))
{
Undo.RecordObject(profile, "Clear");
if (EditorUtility.DisplayDialog("提醒", "是否确定清空列表?", "确定", "取消"))
{
profile.BuildTasks.Clear();
}
}
GUI.color = Color.cyan;
if (GUILayout.Button("打包", "ButtonRight"))
{
if (EditorUtility.DisplayDialog("提醒", "打包需要耗费一定时间,是否确定开始?", "确定", "取消"))
{
StringBuilder sb = new StringBuilder();
sb.Append("打包报告:\r\n");
for (int i = 0; i < profile.BuildTasks.Count; i++)
{
EditorUtility.DisplayProgressBar("Build", "Building...", i + 1 / profile.BuildTasks.Count);
var task = profile.BuildTasks[i];
List<EditorBuildSettingsScene> buildScenes = new List<EditorBuildSettingsScene>();
for (int j = 0; j < task.SceneAssets.Count; j++)
{
var scenePath = AssetDatabase.GetAssetPath(task.SceneAssets[j]);
if (!string.IsNullOrEmpty(scenePath))
{
buildScenes.Add(new EditorBuildSettingsScene(scenePath, true));
}
}
//profile.BuildTasks[i].preferb.GetComponent<LoadSceneByAssetBundle>().m_ABScenesSeriesFileName = profile.BuildTasks[i].ABScenesFileName;
//profile.BuildTasks[i].preferb.GetComponent<LoadSceneByAssetBundle>().m_ABFileName = profile.BuildTasks[i].ABSceneName;
//EditorUtility.SetDirty(profile.BuildTasks[i].preferb);
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
//PlayerSettings.productName = task.ProductName;
PlayerSettings.bundleVersion = task.Version;
AssetDatabase.SaveAssets();
string locationPathName = string.Empty;
// 动态设置应用标识和图标
BuildTargetGroup targetGroup = BuildPipeline.GetBuildTargetGroup(task.BuildTarget);
if (targetGroup != BuildTargetGroup.Unknown)
{
PlayerSettings.SetIconsForTargetGroup(targetGroup, new Texture2D[] { task.DefaultIcon });
//PlayerSettings.SetApplicationIdentifier(targetGroup, task.PackageName);
}
if (targetGroup == BuildTargetGroup.Android)
{
locationPathName = $"{task.BuildPath}/{task.ProductName}.apk"; // 指定输出文件为APK格式
}
else
{
locationPathName = $"{task.BuildPath}/{task.ProductName}.exe";
}
var report = BuildPipeline.BuildPlayer(buildScenes.ToArray(), locationPathName, task.BuildTarget, BuildOptions.None);
sb.Append($"[{task.ProductName}] 打包结果: {report.summary.result}\r\n");
}
EditorUtility.ClearProgressBar();
Debug.Log(sb.ToString());
}
return;
}
GUI.color = Color.white;
}
GUILayout.EndHorizontal();
scroll = GUILayout.BeginScrollView(scroll);
{
for (int i = 0; i < profile.BuildTasks.Count; i++)
{
var task = profile.BuildTasks[i];
if (!foldoutMap.ContainsKey(task)) foldoutMap.Add(task, true);
GUILayout.BeginHorizontal("Badge");
GUI.color = Color.green;
GUILayout.Label($"#{i + 1}", GUILayout.Width(30));
GUI.color = Color.white;
GUILayout.Space(12);
foldoutMap[task] = EditorGUILayout.Foldout(foldoutMap[task], $"{task.ProductName}", true);
GUILayout.Label(string.Empty);
if (GUILayout.Button(EditorGUIUtility.IconContent("TreeEditor.Trash"), "IconButton", GUILayout.Width(20)))
{
Undo.RecordObject(profile, "Delete Task");
foldoutMap.Remove(task);
profile.BuildTasks.Remove(task);
break;
}
if (GUILayout.Button("↑", "MiniButtonLeft", GUILayout.Width(20)))
{
MoveTaskUp(task);
}
if (GUILayout.Button("↓", "MiniButtonMid", GUILayout.Width(20)))
{
MoveTaskDown(task);
}
if (GUILayout.Button("复制", "MiniButtonMid", GUILayout.Width(30)))
{
CopyTask(task);
}
GUILayout.EndHorizontal();
if (foldoutMap[task])
{
GUILayout.BeginVertical("Box");
GUILayout.BeginHorizontal();
GUILayout.Label("打包场景:", GUILayout.Width(70));
if (GUILayout.Button(EditorGUIUtility.IconContent("Toolbar Plus More"), GUILayout.Width(28)))
{
task.SceneAssets.Add(null);
}
GUILayout.EndHorizontal();
if (task.SceneAssets.Count > 0)
{
GUILayout.BeginHorizontal();
GUILayout.Space(75);
GUILayout.BeginVertical("Badge");
for (int j = 0; j < task.SceneAssets.Count; j++)
{
var sceneAsset = task.SceneAssets[j];
GUILayout.BeginHorizontal();
GUILayout.Label($"{j + 1}.", GUILayout.Width(20));
task.SceneAssets[j] = EditorGUILayout.ObjectField(sceneAsset, typeof(SceneAsset), false) as SceneAsset;
if (GUILayout.Button("↑", "MiniButtonLeft", GUILayout.Width(20)))
{
if (j > 0)
{
Undo.RecordObject(profile, "Move Up Scene Assets");
var temp = task.SceneAssets[j - 1];
task.SceneAssets[j - 1] = sceneAsset;
task.SceneAssets[j] = temp;
}
}
if (GUILayout.Button("↓", "MiniButtonMid", GUILayout.Width(20)))
{
if (j < task.SceneAssets.Count - 1)
{
Undo.RecordObject(profile, "Move Down Scene Assets");
var temp = task.SceneAssets[j + 1];
task.SceneAssets[j + 1] = sceneAsset;
task.SceneAssets[j] = temp;
}
}
if (GUILayout.Button(EditorGUIUtility.IconContent("Toolbar Plus"), "MiniButtonMid", GUILayout.Width(20)))
{
Undo.RecordObject(profile, "Add Scene Assets");
task.SceneAssets.Insert(j + 1, null);
break;
}
if (GUILayout.Button(EditorGUIUtility.IconContent("Toolbar Minus"), "MiniButtonMid", GUILayout.Width(20)))
{
Undo.RecordObject(profile, "Delete Scene Assets");
task.SceneAssets.RemoveAt(j);
break;
}
GUILayout.EndHorizontal();
}
GUILayout.EndVertical();
GUILayout.EndHorizontal();
}
GUILayout.BeginHorizontal();
GUILayout.Label("产品名称:", GUILayout.Width(70));
var newPN = GUILayout.TextField(task.ProductName);
if (task.ProductName != newPN)
{
Undo.RecordObject(profile, "Product Name");
task.ProductName = newPN;
serializedProfile.ApplyModifiedProperties(); // 应用修改
}
GUILayout.EndHorizontal();
GUILayout.BeginHorizontal();
GUILayout.Label("打包平台:", GUILayout.Width(70));
var newBT = (BuildTarget)EditorGUILayout.EnumPopup(task.BuildTarget);
if (task.BuildTarget != newBT)
{
Undo.RecordObject(profile, "Build Target");
task.BuildTarget = newBT;
}
GUILayout.EndHorizontal();
GUILayout.BeginHorizontal();
GUILayout.Label("打包路径:", GUILayout.Width(70));
GUILayout.TextField(task.BuildPath);
if (GUILayout.Button("Browse", GUILayout.Width(60)))
{
task.BuildPath = EditorUtility.SaveFolderPanel("Build Path", task.BuildPath, "");
}
GUILayout.EndHorizontal();
GUILayout.BeginHorizontal();
GUILayout.Label("默认图标:", GUILayout.Width(70));
var newIcon = (Texture2D)EditorGUILayout.ObjectField(task.DefaultIcon, typeof(Texture2D), false);
if (task.DefaultIcon != newIcon)
{
Undo.RecordObject(profile, "Default Icon");
task.DefaultIcon = newIcon;
serializedProfile.ApplyModifiedProperties(); // 应用修改
}
GUILayout.EndHorizontal();
GUILayout.BeginHorizontal();
GUILayout.Label("版本号:", GUILayout.Width(70));
var newVersion = GUILayout.TextField(task.Version);
if (task.Version != newVersion)
{
Undo.RecordObject(profile, "Version");
task.Version = newVersion;
serializedProfile.ApplyModifiedProperties(); // 应用修改
}
GUILayout.EndHorizontal();
GUILayout.BeginHorizontal();
GUILayout.Label("包名:", GUILayout.Width(70));
var newPackageName = GUILayout.TextField(task.PackageName);
if (task.PackageName != newPackageName)
{
Undo.RecordObject(profile, "Package Name");
task.PackageName = newPackageName;
serializedProfile.ApplyModifiedProperties(); // 应用修改
}
GUILayout.EndHorizontal();
/* GUILayout.BeginHorizontal();
GUILayout.Label("需要修改的预制体:", GUILayout.Width(70));
var newpreferb = (GameObject)EditorGUILayout.ObjectField(task.preferb, typeof(GameObject), false);
if (task.preferb != newpreferb)
{
Undo.RecordObject(profile, "Default preferb");
task.preferb = newpreferb;
serializedProfile.ApplyModifiedProperties(); // 应用修改
}
GUILayout.EndHorizontal();
GUILayout.BeginHorizontal();
GUILayout.Label("文件名:", GUILayout.Width(70));
var ABScenesFileName = GUILayout.TextField(task.ABScenesFileName);
if (task.ABScenesFileName != ABScenesFileName)
{
Undo.RecordObject(profile, "ABScenesFileName");
task.ABScenesFileName = ABScenesFileName;
serializedProfile.ApplyModifiedProperties(); // 应用修改
}
GUILayout.EndHorizontal();
GUILayout.BeginHorizontal();
GUILayout.Label("AB场景名:", GUILayout.Width(70));
var newABSceneName = GUILayout.TextField(task.ABSceneName);
if (task.ABSceneName != newABSceneName)
{
Undo.RecordObject(profile, "ABSceneName");
task.ABSceneName = newABSceneName;
serializedProfile.ApplyModifiedProperties(); // 应用修改
}
GUILayout.EndHorizontal();*/
GUILayout.BeginHorizontal();
GUILayout.FlexibleSpace(); // 灵活空间使按钮居中
GUI.color = Color.green;
if (GUILayout.Button("打包", GUILayout.Width(100)))
{
Pack(task);
}
GUI.color = Color.white;
GUILayout.FlexibleSpace();
GUILayout.EndHorizontal();
GUILayout.EndVertical();
}
}
}
GUILayout.EndScrollView();
serializedObject.ApplyModifiedProperties();
if (GUI.changed) EditorUtility.SetDirty(profile);
}
private void Pack(BuildTask task)
{
StringBuilder sb = new StringBuilder();
sb.Append("打包报告:\r\n");
List<EditorBuildSettingsScene> buildScenes = new List<EditorBuildSettingsScene>();
foreach (var sceneAsset in task.SceneAssets)
{
var scenePath = AssetDatabase.GetAssetPath(sceneAsset);
if (!string.IsNullOrEmpty(scenePath))
{
buildScenes.Add(new EditorBuildSettingsScene(scenePath, true));
}
}
PlayerSettings.productName = task.ProductName;
PlayerSettings.bundleVersion = task.Version;
AssetDatabase.SaveAssets();
string locationPathName = string.Empty;
// 动态设置应用标识和图标
BuildTargetGroup targetGroup = BuildPipeline.GetBuildTargetGroup(task.BuildTarget);
if (targetGroup != BuildTargetGroup.Unknown)
{
if (task.DefaultIcon != null)
{
PlayerSettings.SetIconsForTargetGroup(targetGroup, new Texture2D[] { task.DefaultIcon });
}
PlayerSettings.SetApplicationIdentifier(targetGroup, task.PackageName);
}
if (targetGroup == BuildTargetGroup.Android)
{
locationPathName = $"{task.BuildPath}/{task.ProductName}.apk"; // 指定输出文件为APK格式
}
else
{
locationPathName = $"{task.BuildPath}/{task.ProductName}.exe";
}
var report = BuildPipeline.BuildPlayer(buildScenes.ToArray(), locationPathName, task.BuildTarget, BuildOptions.None);
sb.Append($"[{task.ProductName}] 打包结果: {report.summary.result}\r\n");
Debug.Log(sb.ToString());
}
private void MoveTaskUp(BuildTask task)
{
int index = profile.BuildTasks.IndexOf(task);
if (index > 0)
{
Undo.RecordObject(profile, "Move Task Up");
profile.BuildTasks.RemoveAt(index);
profile.BuildTasks.Insert(index - 1, task);
}
}
private void MoveTaskDown(BuildTask task)
{
int index = profile.BuildTasks.IndexOf(task);
if (index < profile.BuildTasks.Count - 1)
{
Undo.RecordObject(profile, "Move Task Down");
profile.BuildTasks.RemoveAt(index);
profile.BuildTasks.Insert(index + 1, task);
}
}
private void CopyTask(BuildTask task)
{
Undo.RecordObject(profile, "Copy Task");
var copy = new BuildTask
{
ProductName = task.ProductName,
Version = task.Version,
BuildTarget = task.BuildTarget,
BuildPath = task.BuildPath,
SceneAssets = new List<SceneAsset>(task.SceneAssets),
DefaultIcon = task.DefaultIcon,
PackageName = task.PackageName
};
profile.BuildTasks.Add(copy);
}
}
创建ScriptableObject
就点击它,就创建出来了
创建出来的这个长这样
有问题私聊,看到了就回复,看不到就抱歉了