381 lines
12 KiB
C#
381 lines
12 KiB
C#
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"
|
||
};
|
||
}
|
||
}
|