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