AlicizaX/Client/Assets/Editor/Build/BuildWindow/AdvancedBuildWindow.cs

381 lines
12 KiB
C#
Raw Normal View History

2025-02-06 17:59:35 +08:00
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using AlicizaX.Resource.Runtime;
using UnityEditor;
using UnityEditor.Build.Reporting;
using UnityEngine;
using YooAsset;
using YooAsset.Editor;
public class AdvancedBuildWindow : EditorWindow
{
[MenuItem("开发工具/打包工具")]
public static void ShowWindow()
{
GetWindow<AdvancedBuildWindow>("Build Window", true);
}
private int _selectedTab;
private readonly string[] _tabLabels = { "AB包构建", "整包构建" };
// AB包构建配置
private BuildTarget _abBuildTarget = BuildTarget.StandaloneWindows64;
private string _outputPath = "Builds/AB";
private string _packageVersion;
private bool _copyAfterBuild;
private string _copyDestination;
private ECompressOption _compressOption = ECompressOption.LZ4;
private EFileNameStyle _fileNameStyle = EFileNameStyle.BundleName_HashName;
private EBuildinFileCopyOption _copyOption = EBuildinFileCopyOption.ClearAndCopyByTags;
private string _copyParams = "Launch";
private bool _enableSharePack = true;
private string _selectedEncryption;
private string _selectedPackage;
// 整包构建配置
private BuildTarget _appBuildTarget = BuildTarget.StandaloneWindows64;
private string _appOutputPath = "Builds/App";
private List<SceneAsset> _scenes = new List<SceneAsset>();
private bool _developmentBuild;
private Vector2 _scrollPosition;
private List<string> _encryptionClasses;
private List<string> _buildPackageNames;
private void OnEnable()
{
LoadEncryptionClasses();
LoadBuildPackageNames();
GeneratePackageVersion();
}
private void GeneratePackageVersion()
{
int totalMinutes = DateTime.Now.Hour * 60 + DateTime.Now.Minute;
_packageVersion = DateTime.Now.ToString("yyyy-MM-dd") + "-" + totalMinutes;
}
private void LoadEncryptionClasses()
{
_encryptionClasses = AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(a => a.GetTypes())
.Where(t => typeof(IEncryptionServices).IsAssignableFrom(t) && !t.IsAbstract)
.Select(t => t.FullName)
.ToList();
}
private void LoadBuildPackageNames()
{
_buildPackageNames = new List<string>();
foreach (var package in AssetBundleCollectorSettingData.Setting.Packages)
{
_buildPackageNames.Add(package.PackageName);
}
}
private void OnGUI()
{
_selectedTab = GUILayout.Toolbar(_selectedTab, _tabLabels);
_scrollPosition = EditorGUILayout.BeginScrollView(_scrollPosition);
{
switch (_selectedTab)
{
case 0:
DrawABBuildTab();
break;
case 1:
DrawAppBuildTab();
break;
}
}
EditorGUILayout.EndScrollView();
}
private void DrawABBuildTab()
{
EditorGUILayout.Space();
EditorGUILayout.LabelField("AB包构建配置", EditorStyles.boldLabel);
// 基本配置
DrawBuildTarget(ref _abBuildTarget);
DrawPathSelection("输出路径:", ref _outputPath);
DrawPackageVersion();
// 高级配置
EditorGUILayout.Space();
EditorGUILayout.LabelField("高级选项", EditorStyles.boldLabel);
_compressOption = (ECompressOption)EditorGUILayout.EnumPopup("压缩方式:", _compressOption);
_fileNameStyle = (EFileNameStyle)EditorGUILayout.EnumPopup("文件命名风格:", _fileNameStyle);
_copyOption = (EBuildinFileCopyOption)EditorGUILayout.EnumPopup("内置文件拷贝选项:", _copyOption);
_copyParams = EditorGUILayout.TextField("拷贝参数:", _copyParams);
_enableSharePack = EditorGUILayout.Toggle("启用共享打包:", _enableSharePack);
DrawEncryptionSelection();
DrawPackageSelection();
// 拷贝配置
EditorGUILayout.Space();
_copyAfterBuild = EditorGUILayout.BeginToggleGroup("构建后拷贝", _copyAfterBuild);
DrawPathSelection("拷贝目标:", ref _copyDestination);
EditorGUILayout.EndToggleGroup();
// 操作按钮
EditorGUILayout.Space();
if (GUILayout.Button("构建AB包", GUILayout.Height(30)))
{
BuildABPackage();
}
if (GUILayout.Button("构建热更程序集", GUILayout.Height(30)))
{
BuildDLLCommand.BuildAndCopyDlls();
}
}
private void DrawAppBuildTab()
{
EditorGUILayout.Space();
EditorGUILayout.LabelField("整包构建配置", EditorStyles.boldLabel);
DrawBuildTarget(ref _appBuildTarget);
DrawPathSelection("输出路径:", ref _appOutputPath);
_developmentBuild = EditorGUILayout.Toggle("开发模式:", _developmentBuild);
EditorGUILayout.Space();
EditorGUILayout.LabelField("包含场景:", EditorStyles.boldLabel);
DrawSceneList();
EditorGUILayout.Space();
if (GUILayout.Button("构建应用程序", GUILayout.Height(30)))
{
BuildApplication();
}
}
private void DrawBuildTarget(ref BuildTarget target)
{
target = (BuildTarget)EditorGUILayout.EnumPopup("目标平台:", target);
}
private void DrawPathSelection(string label, ref string path)
{
EditorGUILayout.BeginHorizontal();
{
path = EditorGUILayout.TextField(label, path);
if (GUILayout.Button("浏览...", GUILayout.Width(60)))
{
string newPath = EditorUtility.SaveFolderPanel("选择输出目录", path, "");
if (!string.IsNullOrEmpty(newPath))
{
path = newPath;
}
}
}
EditorGUILayout.EndHorizontal();
}
private void DrawPackageVersion()
{
EditorGUILayout.BeginHorizontal();
{
_packageVersion = EditorGUILayout.TextField("版本号:", _packageVersion);
if (GUILayout.Button("生成新版本", GUILayout.Width(100)))
{
GeneratePackageVersion();
}
}
EditorGUILayout.EndHorizontal();
}
private void DrawEncryptionSelection()
{
if (_encryptionClasses == null || _encryptionClasses.Count == 0)
{
EditorGUILayout.HelpBox("未找到加密类实现", MessageType.Info);
return;
}
int selectedIndex = Mathf.Max(0, _encryptionClasses.IndexOf(_selectedEncryption));
selectedIndex = EditorGUILayout.Popup("加密方式:", selectedIndex, _encryptionClasses.ToArray());
_selectedEncryption = _encryptionClasses[selectedIndex];
}
private void DrawPackageSelection()
{
if (_buildPackageNames == null || _buildPackageNames.Count == 0)
{
EditorGUILayout.HelpBox("未找到包", MessageType.Info);
return;
}
int selectedIndex = Mathf.Max(0, _buildPackageNames.IndexOf(_selectedPackage));
selectedIndex = EditorGUILayout.Popup("Package:", selectedIndex, _buildPackageNames.ToArray());
_selectedPackage = _buildPackageNames[selectedIndex];
}
private void DrawSceneList()
{
for (int i = 0; i < _scenes.Count; i++)
{
_scenes[i] = (SceneAsset)EditorGUILayout.ObjectField($"场景 {i + 1}:", _scenes[i], typeof(SceneAsset), false);
}
EditorGUILayout.BeginHorizontal();
{
if (GUILayout.Button("添加场景"))
{
_scenes.Add(null);
}
if (GUILayout.Button("移除最后一个") && _scenes.Count > 0)
{
_scenes.RemoveAt(_scenes.Count - 1);
}
}
EditorGUILayout.EndHorizontal();
}
private void BuildABPackage()
{
try
{
var parameters = new ScriptableBuildParameters
{
BuildOutputRoot = _outputPath,
BuildTarget = _abBuildTarget,
PackageName = _selectedPackage,
BuildBundleType = (int)EBuildBundleType.AssetBundle,
BuildPipeline = EBuildPipeline.ScriptableBuildPipeline.ToString(),
BuildinFileRoot = AssetBundleBuilderHelper.GetStreamingAssetsRoot(),
PackageVersion = _packageVersion,
CompressOption = _compressOption,
FileNameStyle = _fileNameStyle,
VerifyBuildingResult = true,
ClearBuildCacheFiles = false,
BuildinFileCopyOption = _copyOption,
BuildinFileCopyParams = _copyParams,
EnableSharePackRule = _enableSharePack,
EncryptionServices = CreateEncryptionInstance()
};
ScriptableBuildPipeline pipeline = new ScriptableBuildPipeline();
var report = pipeline.Run(parameters, true);
if (report.Success)
{
BuildUpdateData(_packageVersion, _copyDestination);
if (_copyAfterBuild && !string.IsNullOrEmpty(_copyDestination))
{
CopyFiles(report.OutputPackageDirectory, _copyDestination);
}
EditorUtility.DisplayDialog("构建成功", $"AB包构建完成\n输出目录: {report.OutputPackageDirectory}", "确定");
}
else
{
EditorUtility.DisplayDialog("构建失败", $"错误信息: {report.ErrorInfo}", "确定");
}
}
catch (Exception e)
{
Debug.LogException(e);
}
}
private void BuildUpdateData(string version, string outPath)
{
ResourcePatchData updateData = new ResourcePatchData()
{
Version = Application.version,
BundleUrl = $"http://127.0.0.1:8081/res/{version}/",
Notice = "Test Notice",
};
File.WriteAllText(Path.Combine(outPath, "UpdateData.json"), Newtonsoft.Json.JsonConvert.SerializeObject(updateData));
}
private void BuildApplication()
{
try
{
var options = new BuildPlayerOptions
{
scenes = _scenes.Where(s => s != null).Select(s => AssetDatabase.GetAssetPath(s)).ToArray(),
locationPathName = Path.Combine(_appOutputPath, GetExecutableName()),
target = _appBuildTarget,
options = _developmentBuild ? BuildOptions.Development : BuildOptions.None
};
var report = BuildPipeline.BuildPlayer(options);
HandleBuildReport(report);
}
catch (Exception e)
{
EditorUtility.DisplayDialog("错误", $"构建过程中发生异常: {e.Message}", "确定");
}
}
private IEncryptionServices CreateEncryptionInstance()
{
if (string.IsNullOrEmpty(_selectedEncryption)) return null;
var type = Type.GetType(_selectedEncryption);
if (type != null)
{
return (IEncryptionServices)Activator.CreateInstance(type);
}
return null;
}
private void CopyFiles(string source, string destination)
{
try
{
if (!Directory.Exists(destination))
{
Directory.CreateDirectory(destination);
}
foreach (string file in Directory.GetFiles(source))
{
File.Copy(file, Path.Combine(destination, Path.GetFileName(file)), true);
}
Debug.Log($"文件拷贝完成: {source} -> {destination}");
}
catch (Exception e)
{
Debug.LogError($"文件拷贝失败: {e.Message}");
}
}
private void HandleBuildReport(UnityEditor.Build.Reporting.BuildReport report)
{
if (report.summary.result == UnityEditor.Build.Reporting.BuildResult.Succeeded)
{
EditorUtility.DisplayDialog("构建成功",
$"应用程序构建完成!\n输出大小: {report.summary.totalSize / 1024 / 1024}MB", "确定");
}
else
{
EditorUtility.DisplayDialog("构建失败",
$"错误信息: {report.summary}", "确定");
}
}
private string GetExecutableName()
{
return _appBuildTarget switch
{
BuildTarget.StandaloneWindows64 => "Game.exe",
BuildTarget.StandaloneOSX => "Game.app",
BuildTarget.Android => "Game.apk",
_ => "Game"
};
}
}