using System.Collections.Generic; using System.IO; using TEngine.Editor.Resource; using UnityEditor; using UnityEditor.U2D; using UnityEngine; using UnityEngine.U2D; using YooAsset.Editor; public static class BuildBundlesHelper { private static BuildParameters GetParametersFromParams(BuildTarget buildTarget, string buildVersion) { BuildParameters buildParameters = new BuildParameters() { StreamingAssetsRoot = AssetBundleBuilderHelper.GetDefaultStreamingAssetsRoot(), BuildOutputRoot = AssetBundleBuilderHelper.GetDefaultBuildOutputRoot(), BuildTarget = buildTarget, BuildPipeline = AssetBundleBuilderSettingData.Setting.BuildPipeline, BuildMode = AssetBundleBuilderSettingData.Setting.BuildMode, PackageName = AssetBundleBuilderSettingData.Setting.BuildPackage, PackageVersion = buildVersion, VerifyBuildingResult = true, SharedPackRule = new ZeroRedundancySharedPackRule(), EncryptionServices = new FileStreamEncryption(), CompressOption = AssetBundleBuilderSettingData.Setting.CompressOption, OutputNameStyle = AssetBundleBuilderSettingData.Setting.OutputNameStyle, CopyBuildinFileOption = ECopyBuildinFileOption.None, CopyBuildinFileTags = AssetBundleBuilderSettingData.Setting.CopyBuildinFileTags, EnableLog = false, }; if (AssetBundleBuilderSettingData.Setting.BuildPipeline == EBuildPipeline.ScriptableBuildPipeline) { buildParameters.SBPParameters = new BuildParameters.SBPBuildParameters(); buildParameters.SBPParameters.WriteLinkXML = true; } return buildParameters; } [MenuItem("Tools/TestBuildBundles")] public static void TestBuildBundles() { Debug.LogWarning("MakePrefabs Start =================="); MakePrefabs(); Debug.LogWarning("MakePrefabs End =================="); Debug.LogWarning("MakeAtlas Start =================="); MakeAtlas(); AssetDatabase.Refresh(); Debug.LogWarning("MakeAtlas End =================="); Debug.LogWarning("Create YooAsset Package Start =========="); CreateYooAssetPackage(); AssetDatabase.Refresh(); Debug.LogWarning("Create YooAsset Package End =========="); Debug.LogWarning("BuildBundles Start =================="); AssetBundleCollectorSetting setting = AssetDatabase.LoadAssetAtPath("Assets/AssetBundleCollectorSetting.asset"); if (setting == null) { Debug.LogError("不存在的AssetBundleCollectorSetting.asset"); return; } var bundleBuilder = new AssetBundleBuilder(); BuildParameters buildParameters = GetParametersFromParams(BuildTarget.Android, "1.0.0"); string outputDir = $"{buildParameters.BuildOutputRoot}/{buildParameters.BuildTarget.ToString()}"; Debug.LogError($"bundle资源输出目录:{outputDir}"); if (Directory.Exists(outputDir)) Directory.Delete(outputDir, true); for (int i = 0; i < setting.Packages.Count; i++) { var package = setting.Packages[i]; if (package.PackageName == "DefaultPackage") continue; buildParameters.PackageName = package.PackageName; bundleBuilder.Run(buildParameters); } Debug.LogWarning("BuildBundles End =================="); } public static void BuildBundles() { Debug.LogWarning("MakePrefabs Start =================="); MakePrefabs(); Debug.LogWarning("MakePrefabs End =================="); Debug.LogWarning("MakeAtlas Start =================="); MakeAtlas(); AssetDatabase.Refresh(); Debug.LogWarning("MakeAtlas End =================="); Debug.LogWarning("Create YooAsset Package Start =========="); CreateYooAssetPackage(); AssetDatabase.Refresh(); Debug.LogWarning("Create YooAsset Package End =========="); Debug.LogWarning("BuildBundles Start =================="); AssetBundleCollectorSetting setting = AssetDatabase.LoadAssetAtPath("Assets/AssetBundleCollectorSetting.asset"); if (setting == null) { Debug.LogError("不存在的AssetBundleCollectorSetting.asset"); return; } BuildParams bp = BuildParamsHelper.GetBuildParams(); bp.Description(); var bundleBuilder = new AssetBundleBuilder(); BuildParameters buildParameters = null; if (bp.Platform == "Android") buildParameters = GetParametersFromParams(BuildTarget.Android, bp.BuildVersion); else if (bp.Platform == "iOS") buildParameters = GetParametersFromParams(BuildTarget.iOS, bp.BuildVersion); if (buildParameters == null) { Debug.LogError($"不支持的平台:{bp.Platform}"); return; } string outputDir = $"{buildParameters.BuildOutputRoot}/{buildParameters.BuildTarget.ToString()}"; Debug.LogError($"bundle资源输出目录:{outputDir}"); if (Directory.Exists(outputDir)) Directory.Delete(outputDir, true); for (int i = 0; i < setting.Packages.Count; i++) { var package = setting.Packages[i]; if (package.PackageName == "DefaultPackage") continue; buildParameters.PackageName = package.PackageName; bundleBuilder.Run(buildParameters); } Debug.LogWarning("BuildBundles End ==================> exe"); } #region 创建边框预制体 [MenuItem("Tools/MakePrefabs")] public static void MakePrefabsMenuItem() { MakePrefabs(); } /// /// 根据指定文件夹中的PNG图片生成预制体 /// /// 包含PNG图片的文件夹路径 public static void MakePrefabs(string dir = "Assets/AssetRaw/UIRaw/frame_image") { if (!AssetDatabase.IsValidFolder(dir)) { Debug.LogError($"不存在的目录:{dir}"); return; } // 获取文件夹中所有PNG图片 string[] allPics = Directory.GetFiles(dir, "*.png", SearchOption.TopDirectoryOnly); if (allPics.Length == 0) { Debug.LogError($"目录中没有找到PNG图片:{dir}"); return; } // 创建预制体保存目录 string prefabDir = dir.Replace("frame_image", "frame_prefabs"); if (!AssetDatabase.IsValidFolder(prefabDir)) { Directory.CreateDirectory(prefabDir); AssetDatabase.Refresh(); } int successCount = 0; foreach (var picPath in allPics) { if (picPath.EndsWith(".meta")) continue; // 转换为Unity资源路径 string assetPath = picPath.Replace("\\", "/"); // 加载Sprite资源 Sprite sprite = AssetDatabase.LoadAssetAtPath(assetPath); if (sprite == null) { Debug.LogWarning($"无法加载Sprite: {assetPath}"); continue; } // 从文件名提取数字部分作为预制体名称 string fileName = Path.GetFileNameWithoutExtension(assetPath); string prefabName = ExtractNumberFromFileName(fileName); if (string.IsNullOrEmpty(prefabName)) { Debug.LogWarning($"无法从文件名提取数字: {fileName}"); continue; } // 创建预制体 if (CreateFramePrefab(sprite, prefabName, prefabDir)) { successCount++; Debug.Log($"成功创建预制体: {prefabName}"); } } AssetDatabase.Refresh(); Debug.Log($"预制体创建完成,成功创建 {successCount} 个预制体"); } /// /// 从文件名中提取数字部分 /// /// 文件名,如 "frame_2000" /// 提取的数字字符串,如 "2000" private static string ExtractNumberFromFileName(string fileName) { // 查找最后一个下划线的位置 int lastUnderscoreIndex = fileName.LastIndexOf('_'); if (lastUnderscoreIndex >= 0 && lastUnderscoreIndex < fileName.Length - 1) { string numberPart = fileName.Substring(lastUnderscoreIndex + 1); // 验证是否为纯数字 if (System.Text.RegularExpressions.Regex.IsMatch(numberPart, @"^\d+$")) { return numberPart; } } // 如果没有找到下划线,尝试提取文件名中的所有数字 var match = System.Text.RegularExpressions.Regex.Match(fileName, @"\d+"); if (match.Success) { return match.Value; } return null; } /// /// 创建包含Image组件的预制体 /// /// 要使用的Sprite /// 预制体名称 /// 预制体保存目录 /// 是否创建成功 private static bool CreateFramePrefab(Sprite sprite, string prefabName, string prefabDir) { try { // 创建空的GameObject GameObject frameObject = new GameObject(prefabName); // 添加RectTransform组件(UI元素必需) RectTransform rectTransform = frameObject.AddComponent(); // 添加Image组件 UnityEngine.UI.Image imageComponent = frameObject.AddComponent(); imageComponent.sprite = sprite; imageComponent.preserveAspect = true; // 设置RectTransform的大小为图片的实际像素大小 rectTransform.sizeDelta = new Vector2(sprite.rect.width, sprite.rect.height); // 设置为中心对齐 rectTransform.anchorMin = new Vector2(0.5f, 0.5f); rectTransform.anchorMax = new Vector2(0.5f, 0.5f); rectTransform.pivot = new Vector2(0.5f, 0.5f); rectTransform.anchoredPosition = Vector2.zero; // 确保Image组件不会改变原始图片尺寸 imageComponent.type = UnityEngine.UI.Image.Type.Simple; imageComponent.preserveAspect = false; // 改为false,严格按照sizeDelta设置的尺寸显示 // 保存为预制体 string prefabPath = $"{prefabDir}/{prefabName}.prefab"; GameObject prefab = PrefabUtility.SaveAsPrefabAsset(frameObject, prefabPath); // 清理临时GameObject Object.DestroyImmediate(frameObject); return prefab != null; } catch (System.Exception e) { Debug.LogError($"创建预制体失败 {prefabName}: {e.Message}"); return false; } } #endregion #region 创建图集 private static void MakeAtlas() { string dir = $"Assets/AssetRaw/UIRaw"; if (!AssetDatabase.IsValidFolder(dir)) { Debug.LogError($"不存在的目录:{dir}"); } MakeAtlas(dir); } private static void MakeAtlas(string dirPath) { string[] allPics = Directory.GetFiles(dirPath, "*.png", SearchOption.AllDirectories); if (allPics.Length == 0) { Debug.LogError($"不存在的图:{dirPath}"); return; } List sprites = new List(); foreach (var picPath in allPics) { if (picPath.EndsWith(".meta")) continue; var sprite = AssetDatabase.LoadAssetAtPath(picPath); if (sprite != null) { sprites.Add(sprite); } } Debug.LogError(sprites.Count); AtlasUtils.CreateAtlas($"profile_atlas", sprites, dirPath); } #endregion private static void CreateYooAssetPackage() { AssetBundleCollectorSetting setting = AssetDatabase.LoadAssetAtPath("Assets/AssetBundleCollectorSetting.asset"); if (setting == null) { Debug.LogError("不存在的AssetBundleCollectorSetting.asset"); return; } //重置配置 for (int i = 0; i < setting.Packages.Count; i++) { if (setting.Packages[i].PackageName == "DefaultPackage") continue; setting.Packages.RemoveAt(i); i--; } Debug.Log($"packge count:{setting.Packages.Count}"); //创建关卡资源package string dir = $"Assets/AssetRaw/UIRaw"; if (!AssetDatabase.IsValidFolder(dir)) { Debug.LogError($"不存在的目录:{dir}"); } var levelName = "ProfilesFeatureV2"; AssetBundleCollectorPackage package = new AssetBundleCollectorPackage(); package.PackageName = levelName; package.PackageDesc = $"profile玩法资源包"; package.Groups = new List(); AssetBundleCollectorGroup group = new AssetBundleCollectorGroup(); group.GroupName = "default"; group.AssetTags = levelName; group.ActiveRuleName = "EnableGroup"; group.Collectors = new List(); AssetBundleCollector collector = new AssetBundleCollector(); collector.CollectPath = dir; collector.CollectorGUID = AssetDatabase.AssetPathToGUID(collector.CollectPath); collector.CollectorType = ECollectorType.MainAssetCollector; collector.AddressRuleName = nameof(AddressByFileName); collector.PackRuleName = nameof(PackCollector); collector.FilterRuleName = nameof(CollectAll); collector.AssetTags = levelName; group.Collectors.Add(collector); package.Groups.Add(group); setting.Packages.Add(package); AssetDatabase.SaveAssetIfDirty(setting); } }