using XGame.Framework.Asset.Addressable; using XGame.Framework.Asset.Addressable.Data; using System.IO; using System.Linq; using UnityEditor; using UnityEngine; namespace XGame.Editor.Asset { public static partial class AddressableHelper { private static string GetAssetManifestPath(AddressableClassify classify) { switch (classify) { case AddressableClassify.BuiltIn: return PathDefine.BuiltInAssetManifestPath; case AddressableClassify.Tests: return PathDefine.TestAssetsManifestPath; case AddressableClassify.Backup: return PathDefine.AddressableBackupManifestPath; default: return PathDefine.ProductAssetManifestPath; } } /// /// 加载 AddressableAssetInfoManifest /// /// public static AddressableInfosSo LoadAssetManifest(AddressableClassify classify = AddressableClassify.Product) { var manifest = AssetDatabase.LoadAssetAtPath(GetAssetManifestPath(classify)); //if (manifest != null) //{ // manifest.Init(); //} return manifest; } internal static AddressableInfosSo LoadOrCreateManifest(AddressableClassify classify = AddressableClassify.Product) { var manifestPath = GetAssetManifestPath(classify); var manifest = AssetDatabase.LoadAssetAtPath(manifestPath); if (manifest == null) { if ((classify == AddressableClassify.BuiltIn && !Directory.Exists(PathDefine.BuiltInResourcesRelative)) || (classify == AddressableClassify.Tests && !Directory.Exists(PathDefine.TestsToAddressable) && !Directory.Exists(PathDefine.BuiltInResTests))) { //文件夹不存在 return manifest; } if (!Directory.Exists(PathDefine.ConfigsRelative)) { Directory.CreateDirectory(PathDefine.ConfigsRelative); } if (!Directory.Exists(PathDefine.AddressableDataRelative)) { Directory.CreateDirectory(PathDefine.AddressableDataRelative); } manifest = ScriptableObject.CreateInstance(); AssetDatabase.CreateAsset(manifest, manifestPath); } return manifest; } public static bool TryApplyAddressableName(AddressableInfosSo manifest, string guid, string addressableName) { if (manifest == null) { return false; } //待优化 if (IsValidName(addressableName)) { Debug.LogError($"AddressableName repeat. Please rename it. Name:{addressableName} Path:{AssetDatabase.GUIDToAssetPath(guid)}"); return false; } if (manifest.TryApplyAddressableName(guid, addressableName, out var assetInfo)) { var manifestPath = AssetDatabase.GetAssetPath(manifest); if (PathDefine.ProductAssetManifestPath.Equals(manifestPath) || PathDefine.BuiltInAssetManifestPath.Equals(manifestPath)) { ApplyBackupAssetInfo(assetInfo); } return true; } return false; } public static bool TryRemoveAssetByGUID(AddressableInfosSo manifest, string guid) { if (manifest != null && manifest.TryRemoveAssetByGUID(guid)) { var manifestPath = AssetDatabase.GetAssetPath(manifest); if (PathDefine.ProductAssetManifestPath.Equals(manifestPath) || PathDefine.BuiltInAssetManifestPath.Equals(manifestPath)) { //删除备份 var backup = LoadAssetManifest(AddressableClassify.Backup); backup?.TryRemoveAssetByGUID(guid); } return true; } return false; } public static bool RemoveAllInvalidAssets(AddressableInfosSo manifest) { if (manifest != null && manifest.RemoveAllInvalidAssets()) { var manifestPath = AssetDatabase.GetAssetPath(manifest); if (PathDefine.ProductAssetManifestPath.Equals(manifestPath)) { var backup = LoadAssetManifest(AddressableClassify.Backup); backup?.RemoveAllInvalidAssets(); } return true; } return false; } private static void ApplyBackupAssetInfo(AssetInfo assetInfo) { var backup = LoadAssetManifest(AddressableClassify.Backup); if (backup != null) { var isNameDefault = IsDefaultAddressableName(assetInfo.addressableName, assetInfo.assetGUID); if (isNameDefault || !IsValidPath(assetInfo.GetAssetPath())) { //默认名字或者无效资源 backup.TryRemoveAssetByGUID(assetInfo.assetGUID); } else { var assetInfos = backup.assetInfos.ToList(); var index = assetInfos.FindIndex((info => info.assetGUID.Equals(assetInfo.assetGUID))); if (index >= 0) { assetInfos[index] = assetInfo; } else { assetInfos.Add(assetInfo); } backup.SetAssetInfos(assetInfos.ToArray()); } } } /// /// 收集所有自定义的AddressableName /// private static void CollectCustomAddressableNames() { var backup = LoadAssetManifest(AddressableClassify.Backup); if (backup != null) { var assetInfos = backup.GetAssetInfos(); assetInfos.Clear(); AddressableClassify[] operations = { AddressableClassify.BuiltIn, AddressableClassify.Product }; for (int i = 0; i < operations.Length; i++) { var manifest = LoadAssetManifest(operations[i]); if (manifest != null && manifest.assetInfos != null) { foreach (var assetInfo in manifest.assetInfos) { if (IsValidPath(assetInfo.GetAssetPath()) && !IsDefaultAddressableName(assetInfo.addressableName, assetInfo.assetGUID)) { //有效资源并且不是默认名字 assetInfos.Add(assetInfo); } } } } backup.SetAssetInfos(assetInfos.ToArray()); } } internal static bool IsDefaultAddressableName(string addressableName, string guid, System.Func isContantFileName = null) { var assetPath = AssetDatabase.GUIDToAssetPath(guid); if (string.IsNullOrEmpty(addressableName) || string.IsNullOrEmpty(assetPath)) { return false; } var fileName = GetFileNameIncludeI18n(assetPath); if (addressableName.Equals(fileName)) { return true; } if (isContantFileName != null && isContantFileName.Invoke(fileName) == false) { //addressable配置里没有名字为fileName的配置 return false; } var ext = Path.GetExtension(assetPath); if (addressableName.Equals(($"{fileName}{ext.Replace('.', '_')}").ToLower())) { return true; } if (addressableName.Equals(($"{fileName}_{guid.Substring(0, 8)}").ToLower())) { return true; } if (addressableName.Equals(($"{fileName}_{guid}").ToLower())) { return true; } return false; } } }