From c202e21af085f26c4cf1dd6459c1e13cfc7ff162 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=88=E6=80=9D=E6=B5=B7?= <1464576565@qq.com> Date: Tue, 9 Dec 2025 13:52:52 +0800 Subject: [PATCH] opt MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1.取消令牌传递修改 2.资源分帧卸载 --- .../Implement/SetSpriteExtensions.cs | 4 +- .../ResourceExtComponent.Resource.cs | 16 ++- .../Extension/ResourceExtComponent.cs | 103 ++++++++++++------ 3 files changed, 80 insertions(+), 43 deletions(-) diff --git a/Runtime/Resource/Resource/Extension/Implement/SetSpriteExtensions.cs b/Runtime/Resource/Resource/Extension/Implement/SetSpriteExtensions.cs index bc0ebf7..bee34d6 100644 --- a/Runtime/Resource/Resource/Extension/Implement/SetSpriteExtensions.cs +++ b/Runtime/Resource/Resource/Extension/Implement/SetSpriteExtensions.cs @@ -15,7 +15,7 @@ public static class SetSpriteExtensions /// 取消设置资源的Token。 public static void SetSprite(this Image image, string location, bool setNativeSize = false, CancellationToken cancellationToken = default) { - ResourceExtComponent.Instance.SetAssetByResources(SetSpriteObject.Create(image, location, setNativeSize, cancellationToken)).Forget(); + ResourceExtComponent.Instance.SetAssetByResources(SetSpriteObject.Create(image, location, setNativeSize), cancellationToken).Forget(); } /// @@ -26,7 +26,7 @@ public static class SetSpriteExtensions /// 取消设置资源的Token。 public static void SetSprite(this SpriteRenderer spriteRenderer, string location, CancellationToken cancellationToken = default) { - ResourceExtComponent.Instance.SetAssetByResources(SetSpriteObject.Create(spriteRenderer, location, cancellationToken)).Forget(); + ResourceExtComponent.Instance.SetAssetByResources(SetSpriteObject.Create(spriteRenderer, location), cancellationToken).Forget(); } /// diff --git a/Runtime/Resource/Resource/Extension/ResourceExtComponent.Resource.cs b/Runtime/Resource/Resource/Extension/ResourceExtComponent.Resource.cs index 1aa4cc1..c48311c 100644 --- a/Runtime/Resource/Resource/Extension/ResourceExtComponent.Resource.cs +++ b/Runtime/Resource/Resource/Extension/ResourceExtComponent.Resource.cs @@ -83,7 +83,7 @@ namespace AlicizaX.Resource.Runtime /// /// ISetAssetObject。 /// Unity对象类型。 - public async UniTaskVoid SetAssetByResources(ISetAssetObject setAssetObject) where T : UnityEngine.Object + public async UniTaskVoid SetAssetByResources(ISetAssetObject setAssetObject,CancellationToken cancellationToken) where T : UnityEngine.Object { var target = setAssetObject.TargetObject; var location = setAssetObject.Location; @@ -97,16 +97,16 @@ namespace AlicizaX.Resource.Runtime CancelAndCleanupOldRequest(target); // 创建新的加载状态 - var cts = new CancellationTokenSource(); + var linkedTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken); var loadingState = MemoryPool.Acquire(); - loadingState.Cts = cts; + loadingState.Cts = linkedTokenSource; loadingState.Location = location; _loadingStates[target] = loadingState; try { // 等待其他可能正在进行的加载。 - await TryWaitingLoading(location).AttachExternalCancellation(cts.Token); + await TryWaitingLoading(location).AttachExternalCancellation(linkedTokenSource.Token); // 再次检查是否被新请求替换。 if (!IsCurrentLocation(target, location)) @@ -137,7 +137,13 @@ namespace AlicizaX.Resource.Runtime return; } - _resourceModule.LoadAssetAsync(location, typeof(T), 0, _loadAssetCallbacks, setAssetObject); + T resource = await _resourceModule.LoadAssetAsync(location, linkedTokenSource.Token); + if (resource != null) + { + _loadAssetCallbacks?.LoadAssetSuccessCallback.Invoke(location,resource, 0f, setAssetObject); + + } + _assetLoadingList.Remove(location); } } catch (OperationCanceledException) diff --git a/Runtime/Resource/Resource/Extension/ResourceExtComponent.cs b/Runtime/Resource/Resource/Extension/ResourceExtComponent.cs index eeaf8ce..668ead2 100644 --- a/Runtime/Resource/Resource/Extension/ResourceExtComponent.cs +++ b/Runtime/Resource/Resource/Extension/ResourceExtComponent.cs @@ -1,19 +1,22 @@ using System; -using System.Buffers; using System.Collections; using System.Collections.Generic; using AlicizaX.ObjectPool; -using AlicizaX.Resource.Runtime; -using AlicizaX; using Cysharp.Threading.Tasks; using UnityEngine; +using UnityEngine.Serialization; using Object = UnityEngine.Object; namespace AlicizaX.Resource.Runtime { + /// + /// 资源组件拓展。 + /// + [DisallowMultipleComponent] public partial class ResourceExtComponent : MonoBehaviour { public static ResourceExtComponent Instance { private set; get; } + private readonly TimeoutController _timeoutController = new TimeoutController(); /// @@ -22,25 +25,37 @@ namespace AlicizaX.Resource.Runtime private readonly HashSet _assetLoadingList = new HashSet(); /// - /// 检查是否可以释放间隔 - /// - [SerializeField] private float m_CheckCanReleaseInterval = 30f; - - private float m_CheckCanReleaseTime = 0.0f; - - /// - /// 对象池自动释放时间间隔 - /// - [SerializeField] private float m_AutoReleaseInterval = 60f; - - /// - /// 保存加载的图片对象 + /// 检查是否可以释放间隔。 /// [SerializeField] - private LinkedList m_LoadAssetObjectsLinkedList; + private float checkCanReleaseInterval = 30f; + + private float _checkCanReleaseTime = 0.0f; /// - /// 散图集合对象池 + /// 对象池自动释放时间间隔。 + /// + [SerializeField] + private float autoReleaseInterval = 60f; + + /// + /// 每帧最大处理资源数量,用于分帧处理避免卡顿。 + /// + [SerializeField] + private int maxProcessPerFrame = 50; + + /// + /// 当前正在处理的节点,用于分帧处理。 + /// + private LinkedListNode _currentProcessNode; + + /// + /// 保存加载的图片对象。 + /// + private LinkedList _loadAssetObjectsLinkedList; + + /// + /// 散图集合对象池。 /// private IObjectPool _assetItemPool; @@ -48,31 +63,27 @@ namespace AlicizaX.Resource.Runtime #if UNITY_EDITOR public LinkedList LoadAssetObjectsLinkedList { - get => m_LoadAssetObjectsLinkedList; - set => m_LoadAssetObjectsLinkedList = value; + get => _loadAssetObjectsLinkedList; + set => _loadAssetObjectsLinkedList = value; } #endif - private void Awake() - { - Instance = this; - } - private IEnumerator Start() { + Instance = this; yield return new WaitForEndOfFrame(); IObjectPoolModule objectPoolComponent = ModuleSystem.GetModule(); _assetItemPool = objectPoolComponent.CreateMultiSpawnObjectPool( "SetAssetPool", - m_AutoReleaseInterval, 16, 60, 0); - m_LoadAssetObjectsLinkedList = new LinkedList(); + autoReleaseInterval, 16, 60, 0); + _loadAssetObjectsLinkedList = new LinkedList(); InitializedResources(); } private void Update() { - m_CheckCanReleaseTime += Time.unscaledDeltaTime; - if (m_CheckCanReleaseTime < (double)m_CheckCanReleaseInterval) + _checkCanReleaseTime += Time.unscaledDeltaTime; + if (_checkCanReleaseTime < (double)checkCanReleaseInterval) { return; } @@ -80,37 +91,57 @@ namespace AlicizaX.Resource.Runtime ReleaseUnused(); } - /// /// 回收无引用的缓存资产。 + /// 使用分帧处理优化性能,避免一次性处理大量资源导致卡顿。 /// public void ReleaseUnused() { - if (m_LoadAssetObjectsLinkedList == null) + if (_loadAssetObjectsLinkedList == null || _loadAssetObjectsLinkedList.Count == 0) { + _currentProcessNode = null; + _checkCanReleaseTime = 0f; return; } - LinkedListNode current = m_LoadAssetObjectsLinkedList.First; - while (current != null) + // 如果当前没有正在处理的节点,从头开始 + if (_currentProcessNode == null) + { + _currentProcessNode = _loadAssetObjectsLinkedList.First; + } + + int processedCount = 0; + LinkedListNode current = _currentProcessNode; + + // 分帧处理:每帧最多处理 maxProcessPerFrame 个资源 + while (current != null && processedCount < maxProcessPerFrame) { var next = current.Next; + if (current.Value.AssetObject.IsCanRelease()) { _assetItemPool.Unspawn(current.Value.AssetTarget); MemoryPool.Release(current.Value.AssetObject); - m_LoadAssetObjectsLinkedList.Remove(current); + _loadAssetObjectsLinkedList.Remove(current); } current = next; + processedCount++; } - m_CheckCanReleaseTime = 0f; + // 更新当前处理节点 + _currentProcessNode = current; + + // 如果已经处理完所有节点,重置状态 + if (_currentProcessNode == null) + { + _checkCanReleaseTime = 0f; + } } private void SetAsset(ISetAssetObject setAssetObject, Object assetObject) { - m_LoadAssetObjectsLinkedList.AddLast(new LoadAssetObject(setAssetObject, assetObject)); + _loadAssetObjectsLinkedList.AddLast(new LoadAssetObject(setAssetObject, assetObject)); setAssetObject.SetAsset(assetObject); }