using System; using System.Collections.Generic; using System.Threading.Tasks; using Core; using UnityEngine.AddressableAssets; using UnityEngine.ResourceManagement.AsyncOperations; namespace Utils { /// /// Utility class for common Addressables operations. /// Provides generic methods for loading assets by label and creating lookup dictionaries. /// public static class AddressablesUtility { /// /// Load all assets with a specific label and create a dictionary indexed by a key selector. /// /// Type of asset to load /// Type of key for dictionary /// Addressables label to filter by /// Function to extract key from asset (e.g., asset => asset.Id) /// Optional callback for progress updates (0-1) /// Dictionary of assets indexed by key, and operation handle for cleanup public static async Task<(Dictionary dictionary, AsyncOperationHandle> handle)> LoadAssetsByLabelAsync( string label, Func keySelector, Action onProgress = null) { Dictionary dictionary = new Dictionary(); // Load all assets with the specified label AsyncOperationHandle> handle = Addressables.LoadAssetsAsync( label, asset => { // This callback is invoked for each asset as it loads if (asset != null) { TKey key = keySelector(asset); if (key != null && !dictionary.ContainsKey(key)) { dictionary[key] = asset; } } }); // Report progress if callback provided while (!handle.IsDone) { onProgress?.Invoke(handle.PercentComplete); await Task.Yield(); } // Final progress update onProgress?.Invoke(1f); // Check if load was successful if (handle.Status != AsyncOperationStatus.Succeeded) { Logging.Error($"[AddressablesUtility] Failed to load assets with label '{label}': {handle.OperationException?.Message}"); return (dictionary, handle); } Logging.Debug($"[AddressablesUtility] Loaded {dictionary.Count} assets with label '{label}'"); return (dictionary, handle); } /// /// Load a single asset by address /// /// Type of asset to load /// Addressable address/key /// Loaded asset and operation handle for cleanup public static async Task<(TAsset asset, AsyncOperationHandle handle)> LoadAssetAsync(string address) { AsyncOperationHandle handle = Addressables.LoadAssetAsync(address); await handle.Task; if (handle.Status != AsyncOperationStatus.Succeeded) { Logging.Warning($"[AddressablesUtility] Failed to load asset '{address}': {handle.OperationException?.Message}"); return (default(TAsset), handle); } return (handle.Result, handle); } /// /// Safely release an Addressables handle /// public static void ReleaseHandle(AsyncOperationHandle handle) { if (handle.IsValid()) { Addressables.Release(handle); } } } }