using System; using System.Collections.Generic; using System.IO; using System.Linq; using UnityEditor; using UnityEngine; using YooAsset; using YooAsset.Editor; public class AssetBundleBuildTab : EditorWindowTabBase { 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 List _encryptionClasses; private List _buildPackageNames; internal override 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(); foreach (var package in AssetBundleCollectorSettingData.Setting.Packages) { _buildPackageNames.Add(package.PackageName); } } internal override void OnGUI() { base.OnGUI(); DrawABBuildTab(); } 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 DrawBuildTarget(ref BuildTarget target) { target = (BuildTarget)EditorGUILayout.EnumPopup("目标平台:", target); } 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 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 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 IEncryptionServices CreateEncryptionInstance() { if (string.IsNullOrEmpty(_selectedEncryption)) return null; var type = Type.GetType(_selectedEncryption); if (type != null) { return (IEncryptionServices)Activator.CreateInstance(type); } return null; } }