using System; using System.Collections.Generic; using System.IO; using UnityEditor; using UnityEditor.U2D; using UnityEngine; using UnityEngine.U2D; using YooAsset.Editor; namespace Stary.Evo.Editor { public class MarkAdressable { private static AssetBundleCollectorPackage package; private static string _packageName; public static string ArtRoot { get { return Application.dataPath + "/Art"; } } public static void AddArtMark(Action complete) { _packageName = BuildArtAssetWindow.GetBuildPackageName(); AssetBundleCollectorPackage assetBundleCollectorPackage = null; foreach (var package in AssetBundleCollectorSettingData.Setting.Packages) { if (package.PackageName ==_packageName) { assetBundleCollectorPackage = package; } } if (assetBundleCollectorPackage != null) { YooAsset.Editor.AssetBundleCollectorSettingData.RemovePackage(assetBundleCollectorPackage); } MarkArt(); CollectSVC(ArtRoot, _packageName,complete); } #region 自动标记 public static Dictionary addressDic = new Dictionary(); public static Dictionary collectorGroupDic = new Dictionary(); public static void MarkArt() { addressDic.Clear(); collectorGroupDic.Clear(); ///创建分组 string remotedRoot = $"{ArtRoot}/{_packageName}"; DirectoryInfo[] dirs = new DirectoryInfo(remotedRoot).GetDirectories(); var setting = YooAsset.Editor.AssetBundleCollectorSettingData.Setting; setting.ShowPackageView = true; setting.UniqueBundleName = true; //创建Package文件 package = YooAsset.Editor.AssetBundleCollectorSettingData.CreatePackage(_packageName); //检测Packages是否存在TestPackage package.PackageName = _packageName; package.EnableAddressable = true; package.IncludeAssetGUID = true; package.AutoCollectShaders = true; package.IgnoreRuleName = "NormalIgnoreRule"; //检测Packages是否存在Group foreach (var info in dirs) { string groupName = info.Name; if (info.Name == "Scenes"||info.Name == "Config") { AssetBundleCollectorGroup collectorGroup = YooAsset.Editor.AssetBundleCollectorSettingData.CreateGroup(package, groupName); collectorGroup.AssetTags = groupName; if (!collectorGroupDic.ContainsKey(groupName)) { collectorGroupDic.Add(groupName, collectorGroup); } else { Debug.LogError("分组 : " + groupName + "已存在,请检查资源目录,避免重复"); } AutoMarkRootAddress(info); } } // AssetDatabase.SaveAssets(); // AssetDatabase.Refresh(); MarkStatus(); YooAsset.Editor.AssetBundleCollectorSettingData.SaveFile(); // CreateRes(); Debug.Log("MarkAsset Successful"); } public static void AutoMarkRootAddress(DirectoryInfo dir) { List fileInfos = new List(); FilesUtils.GetFiles(dir.FullName, ref fileInfos); //检测用户config下是否存在config文件 if (dir.Name == "Config") { List fileNewInfos = new List(); foreach (var file in fileInfos) { if (Path.GetExtension(file) != ".meta") { fileNewInfos.Add(file); } } } if (fileInfos != null && fileInfos.Count > 0) { foreach (var file in fileInfos) { if (Path.GetExtension(file) != ".meta" && Path.GetExtension(file) != ".spriteatlas") { // string[] dirSplit = file.Split(new string[] { $"AddressableRes\\{dir.Name}\\" }, // StringSplitOptions.RemoveEmptyEntries); // string address = (dirSplit[dirSplit.Length - 1]).Replace("\\", "/"); // Debug.Log("address:" + address); string groupName = dir.Name; string assetPath = FilesUtils.AbsoluteToRelativePath("Assets", file); //Asset到文件的路径 var guid = AssetDatabase.AssetPathToGUID(assetPath); var group = collectorGroupDic[groupName]; if (group != null) { AssetBundleCollector collector = new AssetBundleCollector() { CollectPath = assetPath, CollectorGUID = guid, CollectorType = ECollectorType.MainAssetCollector, AddressRuleName = nameof(AddressByFolderAndFileName), AssetTags = groupName, }; //TODO 暂时不设置 // 如果是video目录,设置 // if (groupName == "Video") // { // collector.PackRuleName = nameof(PackVideoFile); // } YooAsset.Editor.AssetBundleCollectorSettingData.CreateCollector(group, collector); Debug.Log("GetAssetAddress:" + GetAssetAddress(file)); AddAddressInfo(file, GetAssetAddress(file)); } else { Debug.LogError("分组 = " + groupName + "不存在"); } } } } } #region 图集 public static void AutoCreateSpriteAtlas(string domainRootRes) { string AtlasRemotedRoot = domainRootRes + "/SpriteAtlas"; string SpriteRemotedAtlas = domainRootRes + "/Sprites"; DirectoryInfo[] remotedirs = new DirectoryInfo(SpriteRemotedAtlas).GetDirectories(); foreach (var info in remotedirs) { AddSpriteAtlas(SpriteRemotedAtlas + "/" + info.Name, SpriteRemotedAtlas, AtlasRemotedRoot, info); } } /// /// 自动创建图集 /// /// 路径 /// 文件夹 private static void AddSpriteAtlas(string path, string atlasRoot, string spriteAtlas, DirectoryInfo dir) { var groupname = "SpriteAtlas"; var dirs = dir.GetDirectories(); if (dirs == null || dirs.Length == 0) { string name = path.Replace(atlasRoot + "/", string.Empty).Replace("/", "_"); string filePath = $"{spriteAtlas}/{name}.spriteatlas"; // string[] dirSplit = // filePath.Split(new string[] { $"AddressableRes/{Path.GetFileName(spriteAtlas)}" }, // StringSplitOptions.RemoveEmptyEntries); // string address = (dirSplit[dirSplit.Length - 1]).Substring(1).Replace("\\", "/"); // Debug.Log("spriteatlasaddress:" + address); int assetIndex = filePath.IndexOf("Assets"); string guidPath = filePath.Remove(0, assetIndex); if (!File.Exists(filePath)) { SpriteAtlas atlas = new SpriteAtlas(); //设置打包参数 SpriteAtlasPackingSettings packSetting = new SpriteAtlasPackingSettings() { blockOffset = 1, enableRotation = true, enableTightPacking = false, padding = 2, }; atlas.SetPackingSettings(packSetting); //设置打包后Texture图集信息 SpriteAtlasTextureSettings textureSettings = new SpriteAtlasTextureSettings() { readable = false, generateMipMaps = false, sRGB = true, filterMode = FilterMode.Bilinear, }; atlas.SetTextureSettings(textureSettings); //设置平台图集大小压缩等信息 TextureImporterPlatformSettings platformSettings = new TextureImporterPlatformSettings() { maxTextureSize = 4096, format = TextureImporterFormat.Automatic, crunchedCompression = true, textureCompression = TextureImporterCompression.Compressed, compressionQuality = 50, }; atlas.SetPlatformSettings(platformSettings); AssetDatabase.CreateAsset(atlas, guidPath); int pathIndex = path.IndexOf("Assets"); string spritePath = path.Remove(0, pathIndex); UnityEngine.Object obj = AssetDatabase.LoadAssetAtPath(spritePath, typeof(UnityEngine.Object)); atlas.Add(new[] { obj }); AssetDatabase.SaveAssets(); AssetDatabase.Refresh(); } var guid = AssetDatabase.AssetPathToGUID(guidPath); var group = collectorGroupDic[groupname]; if (group != null) { AssetBundleCollector collector = new AssetBundleCollector() { CollectPath = guidPath, CollectorGUID = guid, CollectorType = ECollectorType.MainAssetCollector, AddressRuleName = nameof(AddressByFolderAndFileName), AssetTags = groupname, }; YooAsset.Editor.AssetBundleCollectorSettingData.CreateCollector(group, collector); AddAddressInfo(path, GetAssetAddress(path)); } else { Debug.LogError("分组 = " + GetAssetAddress(path) + "不存在"); } AssetDatabase.Refresh(); } else { if (dirs.Length > 0) { foreach (var info in dirs) { AddSpriteAtlas(path + "/" + info.Name, atlasRoot, spriteAtlas, info); } } } } #endregion private static void AddAddressInfo(string assetPath, string address) { if (addressDic.ContainsKey(assetPath)) { Debug.LogError("命名重复,已经存在:" + assetPath); } else { addressDic.Add(assetPath, address); } } private static string GetAssetAddress(string assetPath) { string fileName = Path.GetFileNameWithoutExtension(assetPath); FileInfo fileInfo = new FileInfo(assetPath); return $"{fileInfo.Directory.Name}_{fileName}"; } #endregion /// /// 标记为资源分组 /// private static void MarkStatus() { List deleteList = new List(); for (int i = 0; i < package.Groups.Count; i++) { var group = package.Groups[i]; if (group.GroupName != "Default Local Group" && group.GroupName != "Built In Data") { if (group.Collectors.Count <= 0) { ///删除没有资源的分组 deleteList.Add(group); } } } for (int i = 0; i < deleteList.Count; i++) { package.Groups.Remove(deleteList[i]); } } public static void CollectSVC(string root,string packageName,Action complete) { string remotedRoot = $"{root}/{packageName}/ShaderVariants"; string remotedRootFileName = $"{remotedRoot}/{packageName}.shadervariants"; if (!Directory.Exists(remotedRoot)) { Directory.CreateDirectory(remotedRoot); AssetDatabase.Refresh(); } string localSavePath = FilesUtils.AbsoluteToRelativePath("Assets", remotedRootFileName); //Asset到文件的路径 System.Action completedCallback = () => { ShaderVariantCollection collection = AssetDatabase.LoadAssetAtPath(localSavePath); if (collection != null) { Debug.Log( $"UnityEvo:【{packageName}】ShaderCount : {collection.shaderCount}"); Debug.Log( $"UnityEvo:【{packageName}】VariantCount : {collection.variantCount}"); CreateShaderVariantsGroup(packageName, localSavePath); complete?.Invoke(); } else { throw new Exception("Failed to Collect shader Variants."); } }; ShaderVariantCollector.Run(localSavePath, packageName, 1000, completedCallback); } // 新增方法:创建独立的ShaderVariants分组(防止多个package冲突) private static void CreateShaderVariantsGroup(string packageName, string localSavePath) { string groupname = $"ShaderVariants_{packageName}"; AssetBundleCollectorGroup collectorGroup = null; // 查找或创建package专属分组 foreach (var package in AssetBundleCollectorSettingData.Setting.Packages) { if (package.PackageName == packageName) { collectorGroup = YooAsset.Editor.AssetBundleCollectorSettingData.CreateGroup(package, groupname); break; } } var guid = AssetDatabase.AssetPathToGUID(localSavePath); AssetBundleCollector collector = new AssetBundleCollector() { CollectPath = localSavePath, CollectorGUID = guid, CollectorType = ECollectorType.MainAssetCollector, AddressRuleName = nameof(AddressByFolderAndFileName), PackRuleName = nameof(PackShaderVariants), FilterRuleName = nameof(CollectShaderVariants), AssetTags = groupname, }; YooAsset.Editor.AssetBundleCollectorSettingData.CreateCollector(collectorGroup, collector); YooAsset.Editor.AssetBundleCollectorSettingData.SaveFile(); } } }