新增BuildTool编辑器窗口,集成AssetBundle Browser实现一键打包,自动生成版本化的list.json配置文件,支持同步拷贝到StreamingAssets目录
160 lines
6.2 KiB
C#
160 lines
6.2 KiB
C#
using System;
|
||
using System.IO;
|
||
using System.Reflection;
|
||
using UnityEditor;
|
||
using UnityEngine;
|
||
|
||
public class BuildTool : EditorWindow
|
||
{
|
||
private string buildVersion = "1.0.0";
|
||
|
||
private const string PREF_BUILD_VERSION = "BuildTool_Version";
|
||
|
||
[MenuItem("Tools/Build/一键打包资源 (AB + List)")]
|
||
public static void ShowWindow()
|
||
{
|
||
var window = GetWindow<BuildTool>("一键打包资源");
|
||
window.minSize = new Vector2(400, 100);
|
||
}
|
||
|
||
private void OnEnable()
|
||
{
|
||
buildVersion = EditorPrefs.GetString(PREF_BUILD_VERSION, "1.0.0");
|
||
}
|
||
|
||
private void OnGUI()
|
||
{
|
||
GUILayout.Label("一键打包资源 (AB → List)", EditorStyles.boldLabel);
|
||
EditorGUILayout.Space();
|
||
|
||
buildVersion = EditorGUILayout.TextField("版本号", buildVersion);
|
||
|
||
EditorGUILayout.Space();
|
||
EditorGUILayout.HelpBox("使用 Asset Bundle Browser 的设置进行构建,完成后自动生成 list.json", MessageType.Info);
|
||
|
||
EditorGUILayout.Space();
|
||
|
||
if (GUILayout.Button("开始打包", GUILayout.Height(35)))
|
||
{
|
||
if (string.IsNullOrEmpty(buildVersion))
|
||
{
|
||
EditorUtility.DisplayDialog("错误", "请输入版本号", "确定");
|
||
return;
|
||
}
|
||
|
||
EditorPrefs.SetString(PREF_BUILD_VERSION, buildVersion);
|
||
StartBuild();
|
||
}
|
||
}
|
||
|
||
private void StartBuild()
|
||
{
|
||
try
|
||
{
|
||
// ========== 第1步:调用 ABB 构建 AssetBundle ==========
|
||
Debug.Log("=== 第1步:调用 Asset Bundle Browser 构建 ===");
|
||
EditorUtility.DisplayProgressBar("打包中", "构建 AssetBundle...", 0.0f);
|
||
|
||
// 获取 ABB 窗口类型
|
||
var abbType = Type.GetType("AssetBundleBrowser.AssetBundleBrowserMain, Unity.AssetBundleBrowser.Editor");
|
||
if (abbType == null)
|
||
{
|
||
EditorUtility.ClearProgressBar();
|
||
EditorUtility.DisplayDialog("错误", "未找到 Asset Bundle Browser,请确认已安装该包", "确定");
|
||
return;
|
||
}
|
||
|
||
// 获取/创建 ABB 窗口
|
||
var abbWindow = EditorWindow.GetWindow(abbType);
|
||
|
||
// 通过反射获取 m_BuildTab
|
||
var buildTabField = abbType.GetField("m_BuildTab", BindingFlags.NonPublic | BindingFlags.Instance);
|
||
if (buildTabField == null)
|
||
{
|
||
EditorUtility.ClearProgressBar();
|
||
EditorUtility.DisplayDialog("错误", "无法访问 ABB 构建选项卡", "确定");
|
||
return;
|
||
}
|
||
var buildTab = buildTabField.GetValue(abbWindow);
|
||
|
||
// 获取 ABB 输出路径和 CopyToStreaming 状态(在 ExecuteBuild 之前读取)
|
||
string abbOutputPath = GetABBSettings(buildTab, "m_UserData", "m_OutputPath") as string;
|
||
string fullAbbPath = !string.IsNullOrEmpty(abbOutputPath) ? Path.GetFullPath(abbOutputPath) : null;
|
||
bool copyToStreaming = (bool)GetABBSettings(buildTab, "m_CopyToStreaming", "state");
|
||
|
||
// 通过反射调用 ExecuteBuild(同步执行,内部会处理构建 + 拷贝到 StreamingAssets)
|
||
var executeMethod = buildTab.GetType().GetMethod("ExecuteBuild", BindingFlags.NonPublic | BindingFlags.Instance);
|
||
if (executeMethod == null)
|
||
{
|
||
EditorUtility.ClearProgressBar();
|
||
EditorUtility.DisplayDialog("错误", "无法调用 ABB 构建方法", "确定");
|
||
return;
|
||
}
|
||
executeMethod.Invoke(buildTab, null);
|
||
|
||
AssetDatabase.Refresh();
|
||
|
||
// ========== 第2步:生成 list.json ==========
|
||
Debug.Log("=== 第2步:生成 list.json ===");
|
||
EditorUtility.DisplayProgressBar("打包中", "生成 list.json...", 0.6f);
|
||
|
||
if (string.IsNullOrEmpty(fullAbbPath) || !Directory.Exists(fullAbbPath))
|
||
{
|
||
EditorUtility.ClearProgressBar();
|
||
EditorUtility.DisplayDialog("错误", "ABB 构建后未找到输出目录", "确定");
|
||
return;
|
||
}
|
||
|
||
// 在 ABB 输出目录下生成 list.json
|
||
string listJsonPath = Path.Combine(fullAbbPath, "list.json");
|
||
AssetBundleListGenerator.GenerateList(fullAbbPath, listJsonPath, buildVersion);
|
||
Debug.Log($"list.json 已生成: {listJsonPath}");
|
||
|
||
// 如果 ABB 勾选了 Copy to StreamingAssets,同步复制 list.json 过去
|
||
if (copyToStreaming)
|
||
{
|
||
string streamingAssetsPath = Path.GetFullPath("Assets/StreamingAssets");
|
||
if (Directory.Exists(streamingAssetsPath))
|
||
{
|
||
string destPath = Path.Combine(streamingAssetsPath, "list.json");
|
||
File.Copy(listJsonPath, destPath, true);
|
||
Debug.Log($"list.json 已同步到 StreamingAssets: {destPath}");
|
||
}
|
||
}
|
||
|
||
AssetDatabase.Refresh();
|
||
|
||
EditorUtility.ClearProgressBar();
|
||
|
||
Debug.Log("=== 资源打包完成! ===");
|
||
EditorUtility.DisplayDialog("打包成功",
|
||
$"资源打包完成\n版本号: {buildVersion}\n配置文件: {listJsonPath}" +
|
||
(copyToStreaming ? "\n已同步到: Assets/StreamingAssets/list.json" : ""),
|
||
"确定");
|
||
}
|
||
catch (Exception e)
|
||
{
|
||
EditorUtility.ClearProgressBar();
|
||
Debug.LogError($"打包失败: {e.Message}\n{e.StackTrace}");
|
||
EditorUtility.DisplayDialog("打包失败", $"发生错误: {e.Message}", "确定");
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 通过反射链式读取 ABB BuildTab 中的嵌套字段值
|
||
/// </summary>
|
||
private static object GetABBSettings(object buildTab, params string[] fieldPath)
|
||
{
|
||
object current = buildTab;
|
||
foreach (string fieldName in fieldPath)
|
||
{
|
||
if (current == null) return null;
|
||
var field = current.GetType().GetField(fieldName,
|
||
BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
|
||
if (field == null) return null;
|
||
current = field.GetValue(current);
|
||
}
|
||
return current;
|
||
}
|
||
}
|