1.取消令牌传递修改
2.资源分帧卸载
This commit is contained in:
陈思海 2025-12-09 13:52:52 +08:00
parent 0045d5a7e1
commit c202e21af0
3 changed files with 80 additions and 43 deletions

View File

@ -15,7 +15,7 @@ public static class SetSpriteExtensions
/// <param name="cancellationToken">取消设置资源的Token。</param> /// <param name="cancellationToken">取消设置资源的Token。</param>
public static void SetSprite(this Image image, string location, bool setNativeSize = false, CancellationToken cancellationToken = default) public static void SetSprite(this Image image, string location, bool setNativeSize = false, CancellationToken cancellationToken = default)
{ {
ResourceExtComponent.Instance.SetAssetByResources<Sprite>(SetSpriteObject.Create(image, location, setNativeSize, cancellationToken)).Forget(); ResourceExtComponent.Instance.SetAssetByResources<Sprite>(SetSpriteObject.Create(image, location, setNativeSize), cancellationToken).Forget();
} }
/// <summary> /// <summary>
@ -26,7 +26,7 @@ public static class SetSpriteExtensions
/// <param name="cancellationToken">取消设置资源的Token。</param> /// <param name="cancellationToken">取消设置资源的Token。</param>
public static void SetSprite(this SpriteRenderer spriteRenderer, string location, CancellationToken cancellationToken = default) public static void SetSprite(this SpriteRenderer spriteRenderer, string location, CancellationToken cancellationToken = default)
{ {
ResourceExtComponent.Instance.SetAssetByResources<Sprite>(SetSpriteObject.Create(spriteRenderer, location, cancellationToken)).Forget(); ResourceExtComponent.Instance.SetAssetByResources<Sprite>(SetSpriteObject.Create(spriteRenderer, location), cancellationToken).Forget();
} }
/// <summary> /// <summary>

View File

@ -83,7 +83,7 @@ namespace AlicizaX.Resource.Runtime
/// </summary> /// </summary>
/// <param name="setAssetObject">ISetAssetObject。</param> /// <param name="setAssetObject">ISetAssetObject。</param>
/// <typeparam name="T">Unity对象类型。</typeparam> /// <typeparam name="T">Unity对象类型。</typeparam>
public async UniTaskVoid SetAssetByResources<T>(ISetAssetObject setAssetObject) where T : UnityEngine.Object public async UniTaskVoid SetAssetByResources<T>(ISetAssetObject setAssetObject,CancellationToken cancellationToken) where T : UnityEngine.Object
{ {
var target = setAssetObject.TargetObject; var target = setAssetObject.TargetObject;
var location = setAssetObject.Location; var location = setAssetObject.Location;
@ -97,16 +97,16 @@ namespace AlicizaX.Resource.Runtime
CancelAndCleanupOldRequest(target); CancelAndCleanupOldRequest(target);
// 创建新的加载状态 // 创建新的加载状态
var cts = new CancellationTokenSource(); var linkedTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);
var loadingState = MemoryPool.Acquire<LoadingState>(); var loadingState = MemoryPool.Acquire<LoadingState>();
loadingState.Cts = cts; loadingState.Cts = linkedTokenSource;
loadingState.Location = location; loadingState.Location = location;
_loadingStates[target] = loadingState; _loadingStates[target] = loadingState;
try try
{ {
// 等待其他可能正在进行的加载。 // 等待其他可能正在进行的加载。
await TryWaitingLoading(location).AttachExternalCancellation(cts.Token); await TryWaitingLoading(location).AttachExternalCancellation(linkedTokenSource.Token);
// 再次检查是否被新请求替换。 // 再次检查是否被新请求替换。
if (!IsCurrentLocation(target, location)) if (!IsCurrentLocation(target, location))
@ -137,7 +137,13 @@ namespace AlicizaX.Resource.Runtime
return; return;
} }
_resourceModule.LoadAssetAsync(location, typeof(T), 0, _loadAssetCallbacks, setAssetObject); T resource = await _resourceModule.LoadAssetAsync<T>(location, linkedTokenSource.Token);
if (resource != null)
{
_loadAssetCallbacks?.LoadAssetSuccessCallback.Invoke(location,resource, 0f, setAssetObject);
}
_assetLoadingList.Remove(location);
} }
} }
catch (OperationCanceledException) catch (OperationCanceledException)

View File

@ -1,19 +1,22 @@
using System; using System;
using System.Buffers;
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using AlicizaX.ObjectPool; using AlicizaX.ObjectPool;
using AlicizaX.Resource.Runtime;
using AlicizaX;
using Cysharp.Threading.Tasks; using Cysharp.Threading.Tasks;
using UnityEngine; using UnityEngine;
using UnityEngine.Serialization;
using Object = UnityEngine.Object; using Object = UnityEngine.Object;
namespace AlicizaX.Resource.Runtime namespace AlicizaX.Resource.Runtime
{ {
/// <summary>
/// 资源组件拓展。
/// </summary>
[DisallowMultipleComponent]
public partial class ResourceExtComponent : MonoBehaviour public partial class ResourceExtComponent : MonoBehaviour
{ {
public static ResourceExtComponent Instance { private set; get; } public static ResourceExtComponent Instance { private set; get; }
private readonly TimeoutController _timeoutController = new TimeoutController(); private readonly TimeoutController _timeoutController = new TimeoutController();
/// <summary> /// <summary>
@ -22,25 +25,37 @@ namespace AlicizaX.Resource.Runtime
private readonly HashSet<string> _assetLoadingList = new HashSet<string>(); private readonly HashSet<string> _assetLoadingList = new HashSet<string>();
/// <summary> /// <summary>
/// 检查是否可以释放间隔 /// 检查是否可以释放间隔。
/// </summary>
[SerializeField] private float m_CheckCanReleaseInterval = 30f;
private float m_CheckCanReleaseTime = 0.0f;
/// <summary>
/// 对象池自动释放时间间隔
/// </summary>
[SerializeField] private float m_AutoReleaseInterval = 60f;
/// <summary>
/// 保存加载的图片对象
/// </summary> /// </summary>
[SerializeField] [SerializeField]
private LinkedList<LoadAssetObject> m_LoadAssetObjectsLinkedList; private float checkCanReleaseInterval = 30f;
private float _checkCanReleaseTime = 0.0f;
/// <summary> /// <summary>
/// 散图集合对象池 /// 对象池自动释放时间间隔。
/// </summary>
[SerializeField]
private float autoReleaseInterval = 60f;
/// <summary>
/// 每帧最大处理资源数量,用于分帧处理避免卡顿。
/// </summary>
[SerializeField]
private int maxProcessPerFrame = 50;
/// <summary>
/// 当前正在处理的节点,用于分帧处理。
/// </summary>
private LinkedListNode<LoadAssetObject> _currentProcessNode;
/// <summary>
/// 保存加载的图片对象。
/// </summary>
private LinkedList<LoadAssetObject> _loadAssetObjectsLinkedList;
/// <summary>
/// 散图集合对象池。
/// </summary> /// </summary>
private IObjectPool<AssetItemObject> _assetItemPool; private IObjectPool<AssetItemObject> _assetItemPool;
@ -48,31 +63,27 @@ namespace AlicizaX.Resource.Runtime
#if UNITY_EDITOR #if UNITY_EDITOR
public LinkedList<LoadAssetObject> LoadAssetObjectsLinkedList public LinkedList<LoadAssetObject> LoadAssetObjectsLinkedList
{ {
get => m_LoadAssetObjectsLinkedList; get => _loadAssetObjectsLinkedList;
set => m_LoadAssetObjectsLinkedList = value; set => _loadAssetObjectsLinkedList = value;
} }
#endif #endif
private void Awake()
{
Instance = this;
}
private IEnumerator Start() private IEnumerator Start()
{ {
Instance = this;
yield return new WaitForEndOfFrame(); yield return new WaitForEndOfFrame();
IObjectPoolModule objectPoolComponent = ModuleSystem.GetModule<IObjectPoolModule>(); IObjectPoolModule objectPoolComponent = ModuleSystem.GetModule<IObjectPoolModule>();
_assetItemPool = objectPoolComponent.CreateMultiSpawnObjectPool<AssetItemObject>( _assetItemPool = objectPoolComponent.CreateMultiSpawnObjectPool<AssetItemObject>(
"SetAssetPool", "SetAssetPool",
m_AutoReleaseInterval, 16, 60, 0); autoReleaseInterval, 16, 60, 0);
m_LoadAssetObjectsLinkedList = new LinkedList<LoadAssetObject>(); _loadAssetObjectsLinkedList = new LinkedList<LoadAssetObject>();
InitializedResources(); InitializedResources();
} }
private void Update() private void Update()
{ {
m_CheckCanReleaseTime += Time.unscaledDeltaTime; _checkCanReleaseTime += Time.unscaledDeltaTime;
if (m_CheckCanReleaseTime < (double)m_CheckCanReleaseInterval) if (_checkCanReleaseTime < (double)checkCanReleaseInterval)
{ {
return; return;
} }
@ -80,37 +91,57 @@ namespace AlicizaX.Resource.Runtime
ReleaseUnused(); ReleaseUnused();
} }
/// <summary> /// <summary>
/// 回收无引用的缓存资产。 /// 回收无引用的缓存资产。
/// 使用分帧处理优化性能,避免一次性处理大量资源导致卡顿。
/// </summary> /// </summary>
public void ReleaseUnused() public void ReleaseUnused()
{ {
if (m_LoadAssetObjectsLinkedList == null) if (_loadAssetObjectsLinkedList == null || _loadAssetObjectsLinkedList.Count == 0)
{ {
_currentProcessNode = null;
_checkCanReleaseTime = 0f;
return; return;
} }
LinkedListNode<LoadAssetObject> current = m_LoadAssetObjectsLinkedList.First; // 如果当前没有正在处理的节点,从头开始
while (current != null) if (_currentProcessNode == null)
{
_currentProcessNode = _loadAssetObjectsLinkedList.First;
}
int processedCount = 0;
LinkedListNode<LoadAssetObject> current = _currentProcessNode;
// 分帧处理:每帧最多处理 maxProcessPerFrame 个资源
while (current != null && processedCount < maxProcessPerFrame)
{ {
var next = current.Next; var next = current.Next;
if (current.Value.AssetObject.IsCanRelease()) if (current.Value.AssetObject.IsCanRelease())
{ {
_assetItemPool.Unspawn(current.Value.AssetTarget); _assetItemPool.Unspawn(current.Value.AssetTarget);
MemoryPool.Release(current.Value.AssetObject); MemoryPool.Release(current.Value.AssetObject);
m_LoadAssetObjectsLinkedList.Remove(current); _loadAssetObjectsLinkedList.Remove(current);
} }
current = next; current = next;
processedCount++;
} }
m_CheckCanReleaseTime = 0f; // 更新当前处理节点
_currentProcessNode = current;
// 如果已经处理完所有节点,重置状态
if (_currentProcessNode == null)
{
_checkCanReleaseTime = 0f;
}
} }
private void SetAsset(ISetAssetObject setAssetObject, Object assetObject) private void SetAsset(ISetAssetObject setAssetObject, Object assetObject)
{ {
m_LoadAssetObjectsLinkedList.AddLast(new LoadAssetObject(setAssetObject, assetObject)); _loadAssetObjectsLinkedList.AddLast(new LoadAssetObject(setAssetObject, assetObject));
setAssetObject.SetAsset(assetObject); setAssetObject.SetAsset(assetObject);
} }