Unity 简单使用Addressables加载SpriteAtlas图集资源
思路很简单,传入图集名和资源名,利用Addressables提供的异步加载方式从ab包中加载。加载完成后存储进缓存字典里,以供后续使用。
添加引用计数,防止多个地方使用同一图集时,不会提前释放
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.ResourceManagement.AsyncOperations;
using UnityEngine.U2D.SpriteAtlas;
using System.Collections.Generic;
public class SpriteAtlasManager : MonoBehaviour
{
// 单例实例
private static SpriteAtlasManager _instance;
public static SpriteAtlasManager Instance
{
get
{
if (_instance == null)
{
GameObject go = new GameObject("SpriteAtlasManager");
_instance = go.AddComponent<SpriteAtlasManager>();
DontDestroyOnLoad(go);
}
return _instance;
}
}
// 图集缓存字典
private Dictionary<string, AtlasCacheInfo> _atlasCache =
new Dictionary<string, AtlasCacheInfo>();
/// <summary>
/// 加载Sprite
/// </summary>
/// <param name="atlasName">图集的Addressable名称</param>
/// <param name="spriteName">Sprite在图集中的名称</param>
/// <param name="onComplete">加载完成回调</param>
public void LoadSprite(string atlasName, string spriteName,
System.Action<Sprite> onComplete)
{
// 如果图集已加载
if (_atlasCache.TryGetValue(atlasName, out AtlasCacheInfo cacheInfo))
{
// 直接获取Sprite
Sprite sprite = cacheInfo.Atlas.GetSprite(spriteName);
if (sprite != null)
{
cacheInfo.RefCount++; // 增加引用计数
onComplete?.Invoke(sprite);
}
else
{
Debug.LogError($"图集 {atlasName} 中找不到Sprite: {spriteName}");
onComplete?.Invoke(null);
}
return;
}
// 异步加载图集
AsyncOperationHandle<SpriteAtlas> handle =
Addressables.LoadAssetAsync<SpriteAtlas>(atlasName);
handle.Completed += op =>
{
if (op.Status == AsyncOperationStatus.Succeeded)
{
// 缓存图集
var newCache = new AtlasCacheInfo
{
Handle = handle,
Atlas = op.Result,
RefCount = 1
};
_atlasCache.Add(atlasName, newCache);
// 获取Sprite
Sprite sprite = newCache.Atlas.GetSprite(spriteName);
if (sprite != null)
{
onComplete?.Invoke(sprite);
}
else
{
Debug.LogError($"图集 {atlasName} 中找不到Sprite: {spriteName}");
Addressables.Release(handle); // 立即释放
_atlasCache.Remove(atlasName);
onComplete?.Invoke(null);
}
}
else
{
Debug.LogError($"图集 {atlasName} 加载失败");
onComplete?.Invoke(null);
}
};
}
/// <summary>
/// 释放Sprite
/// </summary>
/// <param name="atlasName">图集的Addressable名称</param>
public void UnloadSprite(string atlasName)
{
if (_atlasCache.TryGetValue(atlasName, out AtlasCacheInfo cacheInfo))
{
cacheInfo.RefCount--;
if (cacheInfo.RefCount <= 0)
{
Addressables.Release(cacheInfo.Handle);
_atlasCache.Remove(atlasName);
}
}
}
// 图集缓存信息
private class AtlasCacheInfo
{
public AsyncOperationHandle<SpriteAtlas> Handle;
public SpriteAtlas Atlas;
public int RefCount; // 引用计数
}
void OnDestroy()
{
// 清理所有缓存
foreach (var pair in _atlasCache)
{
Addressables.Release(pair.Value.Handle);
}
_atlasCache.Clear();
}
}
使用例:
// 在需要加载Sprite的地方调用
SpriteAtlasManager.Instance.LoadSprite("UI_Atlas", "hero_icon", sprite =>
{
if (sprite != null)
{
GetComponent<Image>().sprite = sprite;
}
});
// 当不再需要时释放
SpriteAtlasManager.Instance.UnloadSprite("UI_Atlas");