using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using UnityEditor; using UnityEditor.AddressableAssets; using UnityEditor.AddressableAssets.Settings; using UnityEngine; namespace BrewMonster { public static class AddressableTools { public static string _modelPathPrefixToRemove = "Assets/ModelRenderer/Art/Models"; public static string _gfxPathPrefixToRemove = "Assets/ModelRenderer/Art/Gfx"; public static string _sfxPathPrefixToRemove = "Assets/ModelRenderer/Art/sfx"; private const string _terrainPathPrefix = "Assets/ModelRenderer/Art/Terrain"; [MenuItem("Tools/Addressable/Get All Asset Name")] public static void GetAllAssetName() { AddressableAssetSettings settings = AddressableAssetSettingsDefaultObject.Settings; if (settings == null) { Debug.LogWarning("Addressable settings not found."); return; } var groupNameToEntries = new Dictionary>(); foreach (var group in settings.groups) { if (group == null) continue; var entries = group.entries; // available in most Addressables versions if (entries == null) continue; string groupName = group.Name; if (!groupNameToEntries.TryGetValue(groupName, out var list)) { list = new List(); groupNameToEntries[groupName] = list; } foreach (var entry in entries) { if (entry == null) continue; list.Add(entry); } } var sb = new StringBuilder(); int totalCount = 0; foreach (var kvp in groupNameToEntries.OrderBy(k => k.Key)) { sb.AppendLine($"[Group] {kvp.Key} ({kvp.Value.Count})"); foreach (var e in kvp.Value.OrderBy(e => e.address)) { sb.AppendLine($"- {e.address}"); } sb.AppendLine(); totalCount += kvp.Value.Count; } if (totalCount == 0) { sb.Append("No addressable assets found."); } Debug.Log(sb.ToString()); EditorUtility.DisplayDialog("Get All Asset Name", $"Printed {totalCount} addressable assets to Console.", "OK"); } [MenuItem("Tools/Addressable/Update Addressable Path For Models")] public static void RemovePrefixFromAddresses() { UpdateAddressableAddressesPath("models", _modelPathPrefixToRemove, ".ecm"); } [MenuItem("Tools/Addressable/Update Addressable Path For Gfx")] public static void UpdateAddressablePathForGfx() { UpdateAddressableAddressesPath("gfx", _gfxPathPrefixToRemove, ".gfx"); } [MenuItem("Tools/Addressable/Update Addressable Path For Sfx")] public static void UpdateAddressablePathForSfx() { UpdateAddressableAddressesPath("sfx", _sfxPathPrefixToRemove, ""); } [MenuItem("Tools/Addressable/Update Addressable Path For a61")] public static void UpdateAddressablePathFora61() { UpdateAddressableAddressesPath("a61", _modelPathPrefixToRemove, ""); } [MenuItem("Tools/Addressable/Update Addressable Path For a61 Terrain")] public static void UpdateAddressablePathFora61Terrain() { UpdateAddressableAddressesPath("a61-terrain", _terrainPathPrefix, ".prefab"); } [MenuItem("Tools/Addressable/Update Addressable Path For World")] public static void UpdateAddressablePathForWorld() { UpdateAddressableAddressesPath("world", _modelPathPrefixToRemove, ""); } public static async void UpdateAddressableAddressesPath(string groupName, string prefixToRemove, string subfix) { AddressableAssetSettings settings = AddressableAssetSettingsDefaultObject.Settings; if (settings == null) { Debug.LogWarning("Addressable settings not found."); return; } int updatedCount = 0; int count = 0; foreach (var group in settings.groups) { if (group == null) continue; if (group.Name != groupName) continue; var entries = group.entries; if (entries == null) continue; foreach (var entry in entries) { count++; // show editor progress bar EditorUtility.DisplayProgressBar("Update Addressable Addresses Path", $"Updating {groupName} -- {count} / {entries.Count}", count / entries.Count); if (entry == null) continue; var address = entry.address; if (string.IsNullOrEmpty(address)) continue; string newAddress = address; // Remove prefix if present if (newAddress.StartsWith(prefixToRemove)) { newAddress = newAddress.Substring(prefixToRemove.Length); if (newAddress.StartsWith("/")) newAddress = newAddress.Substring(1); } // remove the current subfix if present int subfixIndex = newAddress.LastIndexOf('.'); if (subfixIndex != -1) { newAddress = newAddress.Substring(0, subfixIndex); } // apply the new subfix newAddress = newAddress + subfix; // Change suffix from .prefab to .ecm if applicable // if (newAddress.EndsWith(".prefab")) // { // newAddress = newAddress.Substring(0, newAddress.Length - ".prefab".Length) + subfix; // } if (newAddress != address) { entry.SetAddress(newAddress); updatedCount++; } await Task.Delay(1); } } EditorUtility.ClearProgressBar(); if (updatedCount > 0) { EditorUtility.SetDirty(settings); AssetDatabase.SaveAssets(); } Debug.Log($"Update Addressable Addresses Path: Updated {updatedCount} entries."); EditorUtility.DisplayDialog("Update Addressable Addresses Path", $"Updated {updatedCount} entries.", "OK"); } /// /// Sets the address of all addressable assets to match their asset path (relative to Assets folder) /// This allows you to load assets using their file path as the key /// [MenuItem("Tools/Addressable/Set Address To Asset Path")] public static void SetAddressToAssetPath() { AddressableAssetSettings settings = AddressableAssetSettingsDefaultObject.Settings; if (settings == null) { Debug.LogWarning("Addressable settings not found."); return; } int updatedCount = 0; var sb = new StringBuilder(); sb.AppendLine("Setting addresses to asset paths:"); sb.AppendLine(); foreach (var group in settings.groups) { if (group == null) continue; var entries = group.entries; if (entries == null) continue; foreach (var entry in entries) { if (entry == null) continue; // Get the asset path (e.g., "Assets/ModelRenderer/Art/Models/...") string assetPath = entry.AssetPath; if (string.IsNullOrEmpty(assetPath)) continue; // Remove "Assets/" prefix to get a cleaner path string newAddress = assetPath; if (newAddress.StartsWith("Assets/")) { newAddress = newAddress.Substring("Assets/".Length); } // Only update if the address is different if (newAddress != entry.address) { string oldAddress = entry.address; entry.SetAddress(newAddress); sb.AppendLine($"[{group.Name}] {oldAddress} �� {newAddress}"); updatedCount++; } } } if (updatedCount > 0) { settings.SetDirty(AddressableAssetSettings.ModificationEvent.EntryModified, null, true); AssetDatabase.SaveAssets(); } sb.AppendLine(); sb.AppendLine($"Updated {updatedCount} entries."); Debug.Log(sb.ToString()); EditorUtility.DisplayDialog("Set Address To Asset Path", $"Updated {updatedCount} entries to use their asset paths.", "OK"); } /// /// Prints the address and GUID for all addressable assets - useful for debugging /// [MenuItem("Tools/Addressable/Print Address and GUID")] public static void PrintAddressAndGUID() { AddressableAssetSettings settings = AddressableAssetSettingsDefaultObject.Settings; if (settings == null) { Debug.LogWarning("Addressable settings not found."); return; } var sb = new StringBuilder(); sb.AppendLine("Addressable Assets (Address �� GUID �� Path):"); sb.AppendLine(); int totalCount = 0; foreach (var group in settings.groups) { if (group == null) continue; var entries = group.entries; if (entries == null) continue; sb.AppendLine($"[Group: {group.Name}]"); foreach (var entry in entries) { if (entry == null) continue; sb.AppendLine($" Address: {entry.address}"); sb.AppendLine($" GUID: {entry.guid}"); sb.AppendLine($" Path: {entry.AssetPath}"); sb.AppendLine(); totalCount++; } } sb.AppendLine($"Total: {totalCount} addressable assets"); Debug.Log(sb.ToString()); EditorUtility.DisplayDialog("Print Address and GUID", $"Printed {totalCount} addressable assets to Console.", "OK"); } } }