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);
}
}
}
}