105 lines
4.1 KiB
C#
105 lines
4.1 KiB
C#
|
|
using System;
|
|||
|
|
using System.Collections.Generic;
|
|||
|
|
using System.Threading.Tasks;
|
|||
|
|
using Core;
|
|||
|
|
using UnityEngine.AddressableAssets;
|
|||
|
|
using UnityEngine.ResourceManagement.AsyncOperations;
|
|||
|
|
|
|||
|
|
namespace Utils
|
|||
|
|
{
|
|||
|
|
/// <summary>
|
|||
|
|
/// Utility class for common Addressables operations.
|
|||
|
|
/// Provides generic methods for loading assets by label and creating lookup dictionaries.
|
|||
|
|
/// </summary>
|
|||
|
|
public static class AddressablesUtility
|
|||
|
|
{
|
|||
|
|
/// <summary>
|
|||
|
|
/// Load all assets with a specific label and create a dictionary indexed by a key selector.
|
|||
|
|
/// </summary>
|
|||
|
|
/// <typeparam name="TAsset">Type of asset to load</typeparam>
|
|||
|
|
/// <typeparam name="TKey">Type of key for dictionary</typeparam>
|
|||
|
|
/// <param name="label">Addressables label to filter by</param>
|
|||
|
|
/// <param name="keySelector">Function to extract key from asset (e.g., asset => asset.Id)</param>
|
|||
|
|
/// <param name="onProgress">Optional callback for progress updates (0-1)</param>
|
|||
|
|
/// <returns>Dictionary of assets indexed by key, and operation handle for cleanup</returns>
|
|||
|
|
public static async Task<(Dictionary<TKey, TAsset> dictionary, AsyncOperationHandle<IList<TAsset>> handle)>
|
|||
|
|
LoadAssetsByLabelAsync<TAsset, TKey>(
|
|||
|
|
string label,
|
|||
|
|
Func<TAsset, TKey> keySelector,
|
|||
|
|
Action<float> onProgress = null)
|
|||
|
|
{
|
|||
|
|
Dictionary<TKey, TAsset> dictionary = new Dictionary<TKey, TAsset>();
|
|||
|
|
|
|||
|
|
// Load all assets with the specified label
|
|||
|
|
AsyncOperationHandle<IList<TAsset>> handle = Addressables.LoadAssetsAsync<TAsset>(
|
|||
|
|
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);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Load a single asset by address
|
|||
|
|
/// </summary>
|
|||
|
|
/// <typeparam name="TAsset">Type of asset to load</typeparam>
|
|||
|
|
/// <param name="address">Addressable address/key</param>
|
|||
|
|
/// <returns>Loaded asset and operation handle for cleanup</returns>
|
|||
|
|
public static async Task<(TAsset asset, AsyncOperationHandle<TAsset> handle)> LoadAssetAsync<TAsset>(string address)
|
|||
|
|
{
|
|||
|
|
AsyncOperationHandle<TAsset> handle = Addressables.LoadAssetAsync<TAsset>(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);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Safely release an Addressables handle
|
|||
|
|
/// </summary>
|
|||
|
|
public static void ReleaseHandle<T>(AsyncOperationHandle<T> handle)
|
|||
|
|
{
|
|||
|
|
if (handle.IsValid())
|
|||
|
|
{
|
|||
|
|
Addressables.Release(handle);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|