using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using UnityEngine; using UnityEngine.AddressableAssets; using UnityEngine.ResourceManagement.AsyncOperations; namespace SoulliesFramework.General { /// /// 静态的Addressables资源加载器,负责加载和释放资源。 /// 警告:此类不处理依赖关系,仅管理通过它加载的资源的生命周期。 /// public static class AssetLoader { // 使用字典缓存已加载资源的句柄,Key为资源的Address。 // 这样可以防止同一资源被重复加载,并方便我们后续释放。 private static Dictionary CachedHandles = new Dictionary(); public static List LoadAssetsWithLabel(string label) where T : Object { return Addressables.LoadAssetsAsync(label, null).WaitForCompletion().ToList(); } public static Task> LoadAssetsWithLabelAsync(string label) where T : Object { return Addressables.LoadAssetsAsync(label, null).Task; } public static T LoadAsset(string address) where T : Object { return Addressables.LoadAssetAsync(address).WaitForCompletion(); } /// /// 异步加载指定类型的资源。 /// /// 要加载的资源类型 (e.g., GameObject, Sprite, AudioClip) /// 资源的Addressable地址 /// 返回加载到的资源,如果失败则返回null public static async Task LoadAssetAsync(string address) where T : Object { // 1. 检查句柄是否已经被缓存 if (CachedHandles.TryGetValue(address, out var handle)) { // 如果句柄存在,直接返回其结果 return handle.Result as T; } // 2. 如果没有缓存,则异步加载资源 AsyncOperationHandle newHandle = Addressables.LoadAssetAsync(address); // 3. 等待加载完成 T result = await newHandle.Task; // 4. 检查加载是否成功,如果成功则缓存句柄 if (newHandle.Status == AsyncOperationStatus.Succeeded) { // 注意:我们缓存的是通用的句柄,而不是带泛型的句柄 CachedHandles[address] = newHandle; return result; } else { Debug.LogError($"[AssetLoader] Failed to load asset at address: {address}"); return null; } } /// /// 释放指定地址的资源。 /// /// 要释放资源的Addressable地址 public static void ReleaseAsset(string address) { if (CachedHandles.TryGetValue(address, out var handle)) { // 从缓存中移除 CachedHandles.Remove(address); // 释放句柄,这会减少资源的引用计数 Addressables.Release(handle); Debug.Log($"[AssetLoader] Released asset: {address}"); } else { Debug.LogWarning($"[AssetLoader] Tried to release an asset that was not loaded through this loader: {address}"); } } /// /// 释放所有通过此类加载的资源。 /// 通常在切换场景或退出游戏时调用。 /// public static void ReleaseAllAssets() { foreach (var pair in CachedHandles) { Addressables.Release(pair.Value); } CachedHandles.Clear(); Debug.Log("[AssetLoader] All cached assets released."); } } }