killapp/Assets/Editor/BuildTool.cs
“虞渠成” d9e66a2327 feat(editor): 新增一键打包AB资源工具,支持自动生成list.json
新增BuildTool编辑器窗口,集成AssetBundle Browser实现一键打包,自动生成版本化的list.json配置文件,支持同步拷贝到StreamingAssets目录
2026-07-15 16:37:05 +08:00

160 lines
6.2 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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;
}
}