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