107 lines
4.0 KiB
C#
107 lines
4.0 KiB
C#
using System.Collections.Generic;
|
||
using System.Linq;
|
||
using System.Threading.Tasks;
|
||
using UnityEngine;
|
||
using UnityEngine.AddressableAssets;
|
||
using UnityEngine.ResourceManagement.AsyncOperations;
|
||
|
||
namespace SoulliesFramework.General
|
||
{
|
||
/// <summary>
|
||
/// 静态的Addressables资源加载器,负责加载和释放资源。
|
||
/// 警告:此类不处理依赖关系,仅管理通过它加载的资源的生命周期。
|
||
/// </summary>
|
||
public static class AssetLoader
|
||
{
|
||
// 使用字典缓存已加载资源的句柄,Key为资源的Address。
|
||
// 这样可以防止同一资源被重复加载,并方便我们后续释放。
|
||
private static Dictionary<string, AsyncOperationHandle> CachedHandles = new Dictionary<string, AsyncOperationHandle>();
|
||
|
||
public static List<T> LoadAssetsWithLabel<T>(string label) where T : Object
|
||
{
|
||
return Addressables.LoadAssetsAsync<T>(label, null).WaitForCompletion().ToList();
|
||
}
|
||
|
||
public static Task<IList<T>> LoadAssetsWithLabelAsync<T>(string label) where T : Object
|
||
{
|
||
return Addressables.LoadAssetsAsync<T>(label, null).Task;
|
||
}
|
||
|
||
public static T LoadAsset<T>(string address) where T : Object
|
||
{
|
||
return Addressables.LoadAssetAsync<T>(address).WaitForCompletion();
|
||
}
|
||
|
||
|
||
|
||
/// <summary>
|
||
/// 异步加载指定类型的资源。
|
||
/// </summary>
|
||
/// <typeparam name="T">要加载的资源类型 (e.g., GameObject, Sprite, AudioClip)</typeparam>
|
||
/// <param name="address">资源的Addressable地址</param>
|
||
/// <returns>返回加载到的资源,如果失败则返回null</returns>
|
||
public static async Task<T> LoadAssetAsync<T>(string address) where T : Object
|
||
{
|
||
// 1. 检查句柄是否已经被缓存
|
||
if (CachedHandles.TryGetValue(address, out var handle))
|
||
{
|
||
// 如果句柄存在,直接返回其结果
|
||
return handle.Result as T;
|
||
}
|
||
|
||
// 2. 如果没有缓存,则异步加载资源
|
||
AsyncOperationHandle<T> newHandle = Addressables.LoadAssetAsync<T>(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;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 释放指定地址的资源。
|
||
/// </summary>
|
||
/// <param name="address">要释放资源的Addressable地址</param>
|
||
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}");
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 释放所有通过此类加载的资源。
|
||
/// 通常在切换场景或退出游戏时调用。
|
||
/// </summary>
|
||
public static void ReleaseAllAssets()
|
||
{
|
||
foreach (var pair in CachedHandles)
|
||
{
|
||
Addressables.Release(pair.Value);
|
||
}
|
||
|
||
CachedHandles.Clear();
|
||
Debug.Log("[AssetLoader] All cached assets released.");
|
||
}
|
||
}
|
||
} |