using System; using System.Collections; using System.Collections.Generic; using Cysharp.Threading.Tasks; using UnityEngine; using UnityEngine.Serialization; using Object = UnityEngine.Object; #if ODIN_INSPECTOR using Sirenix.OdinInspector; #endif namespace TEngine { /// /// 资源组件拓展。 /// [DisallowMultipleComponent] internal partial class ResourceExtComponent : MonoBehaviour { public static ResourceExtComponent Instance { private set; get; } private readonly TimeoutController _timeoutController = new TimeoutController(); /// /// 正在加载的资源列表。 /// private readonly HashSet _assetLoadingList = new HashSet(); /// /// 检查是否可以释放间隔 /// [SerializeField] private float checkCanReleaseInterval = 30f; private float _checkCanReleaseTime = 0.0f; /// /// 对象池自动释放时间间隔 /// [SerializeField] private float autoReleaseInterval = 60f; /// /// 保存加载的图片对象 /// #if ODIN_INSPECTOR [ShowInInspector] #endif private LinkedList _loadAssetObjectsLinkedList; /// /// 散图集合对象池 /// private IObjectPool _assetItemPool; #if UNITY_EDITOR public LinkedList LoadAssetObjectsLinkedList { get => _loadAssetObjectsLinkedList; set => _loadAssetObjectsLinkedList = value; } #endif private IEnumerator Start() { Instance = this; yield return new WaitForEndOfFrame(); IObjectPoolModule objectPoolComponent = ModuleSystem.GetModule(); _assetItemPool = objectPoolComponent.CreateMultiSpawnObjectPool( "SetAssetPool", autoReleaseInterval, 16, 60, 0); _loadAssetObjectsLinkedList = new LinkedList(); InitializedResources(); } private void Update() { _checkCanReleaseTime += Time.unscaledDeltaTime; if (_checkCanReleaseTime < (double)checkCanReleaseInterval) { return; } ReleaseUnused(); } /// /// 回收无引用的缓存资产。 /// #if ODIN_INSPECTOR [Button("Release Unused")] #endif public void ReleaseUnused() { if (_loadAssetObjectsLinkedList == null) { return; } LinkedListNode current = _loadAssetObjectsLinkedList.First; while (current != null) { var next = current.Next; if (current.Value.AssetObject.IsCanRelease()) { _assetItemPool.Unspawn(current.Value.AssetTarget); MemoryPool.Release(current.Value.AssetObject); _loadAssetObjectsLinkedList.Remove(current); } current = next; } _checkCanReleaseTime = 0f; } private void SetAsset(ISetAssetObject setAssetObject, Object assetObject) { _loadAssetObjectsLinkedList.AddLast(new LoadAssetObject(setAssetObject, assetObject)); setAssetObject.SetAsset(assetObject); } private async UniTask TryWaitingLoading(string assetObjectKey) { if (_assetLoadingList.Contains(assetObjectKey)) { try { await UniTask.WaitUntil( () => !_assetLoadingList.Contains(assetObjectKey)) #if UNITY_EDITOR .AttachExternalCancellation(_timeoutController.Timeout(TimeSpan.FromSeconds(60))); _timeoutController.Reset(); #else ; #endif } catch (OperationCanceledException ex) { if (_timeoutController.IsTimeout()) { Log.Error($"LoadAssetAsync Waiting {assetObjectKey} timeout. reason:{ex.Message}"); } } } } } }