diff --git a/UnityProject/Assets/TEngine/Runtime/Modules/ResourceModule/IResourceManager.cs b/UnityProject/Assets/TEngine/Runtime/Modules/ResourceModule/IResourceManager.cs index a9fe3d4d..93a3b2ff 100644 --- a/UnityProject/Assets/TEngine/Runtime/Modules/ResourceModule/IResourceManager.cs +++ b/UnityProject/Assets/TEngine/Runtime/Modules/ResourceModule/IResourceManager.cs @@ -230,7 +230,7 @@ namespace TEngine /// 回调函数。 /// 指定资源包的名称。不传使用默认资源包 /// 要加载资源的类型。 - void LoadAsset(string location, Action callback, string packageName = "") where T : UnityEngine.Object; + UniTaskVoid LoadAsset(string location, Action callback, string packageName = "") where T : UnityEngine.Object; /// /// 同步加载子资源对象。 diff --git a/UnityProject/Assets/TEngine/Runtime/Modules/ResourceModule/ResourceManager.cs b/UnityProject/Assets/TEngine/Runtime/Modules/ResourceModule/ResourceManager.cs index f74d0c23..f4baadbe 100644 --- a/UnityProject/Assets/TEngine/Runtime/Modules/ResourceModule/ResourceManager.cs +++ b/UnityProject/Assets/TEngine/Runtime/Modules/ResourceModule/ResourceManager.cs @@ -109,6 +109,10 @@ namespace TEngine /// private readonly Dictionary _assetInfoMap = new Dictionary(); + /// + /// 正在加载的资源列表。 + /// + private readonly HashSet _assetLoadingList = new HashSet(); #endregion /// @@ -134,6 +138,8 @@ namespace TEngine DefaultPackage = defaultPackage; } + CancellationToken = InstanceRoot.gameObject.GetCancellationTokenOnDestroy(); + IObjectPoolManager objectPoolManager = ModuleImpSystem.GetModule(); SetObjectPoolManager(objectPoolManager); } @@ -253,7 +259,10 @@ namespace TEngine internal override void Shutdown() { + PackageMap.Clear(); m_AssetPool = null; + _assetLoadingList.Clear(); + _assetInfoMap.Clear(); #if !UNITY_WEBGL YooAssets.Destroy(); #endif @@ -554,7 +563,7 @@ namespace TEngine /// 回调函数。 /// 指定资源包的名称。不传使用默认资源包 /// 要加载资源的类型。 - public void LoadAsset(string location, Action callback, string packageName = "") where T : UnityEngine.Object + public async UniTaskVoid LoadAsset(string location, Action callback, string packageName = "") where T : UnityEngine.Object { if (string.IsNullOrEmpty(location)) { @@ -568,6 +577,9 @@ namespace TEngine } string assetObjectKey = GetCacheKey(location, packageName); + + await TryWaitingLoading(assetObjectKey); + AssetObject assetObject = m_AssetPool.Spawn(assetObjectKey); if (assetObject != null) { @@ -575,10 +587,14 @@ namespace TEngine return; } + _assetLoadingList.Add(assetObjectKey); + AssetHandle handle = GetHandleAsync(location, packageName: packageName); handle.Completed += assetHandle => { + _assetLoadingList.Remove(assetObjectKey); + if (assetHandle.AssetObject != null) { assetObject = AssetObject.Create(assetObjectKey, handle.AssetObject, handle,this); @@ -611,7 +627,7 @@ namespace TEngine throw new NotImplementedException(); } - public async UniTask LoadAssetAsync(string location, CancellationToken cancellationToken = default, string packageName = "") where T : UnityEngine.Object + public async UniTask LoadAssetAsync(string location, CancellationToken cancellationToken = default, string packageName = "") where T : UnityEngine.Object { if (string.IsNullOrEmpty(location)) { @@ -619,11 +635,16 @@ namespace TEngine } string assetObjectKey = GetCacheKey(location, packageName); + + await TryWaitingLoading(assetObjectKey); + AssetObject assetObject = m_AssetPool.Spawn(assetObjectKey); if (assetObject != null) { return assetObject.Target as T; } + + _assetLoadingList.Add(assetObjectKey); AssetHandle handle = GetHandleAsync(location, packageName: packageName); @@ -636,6 +657,8 @@ namespace TEngine assetObject = AssetObject.Create(assetObjectKey, handle.AssetObject, handle,this); m_AssetPool.Register(assetObject, true); + + _assetLoadingList.Remove(assetObjectKey); return handle.AssetObject as T; } @@ -649,12 +672,17 @@ namespace TEngine } string assetObjectKey = GetCacheKey(location, packageName); + + await TryWaitingLoading(assetObjectKey); + AssetObject assetObject = m_AssetPool.Spawn(assetObjectKey); if (assetObject != null) { return AssetsReference.Instantiate(assetObject.Target as GameObject, parent, this).gameObject; } + _assetLoadingList.Add(assetObjectKey); + AssetHandle handle = GetHandleAsync(location, packageName: packageName); bool cancelOrFailed = await handle.ToUniTask().AttachExternalCancellation(cancellationToken).SuppressCancellationThrow(); @@ -669,6 +697,8 @@ namespace TEngine assetObject = AssetObject.Create(assetObjectKey, handle.AssetObject, handle,this); m_AssetPool.Register(assetObject, true); + _assetLoadingList.Remove(assetObjectKey); + return gameObject; } @@ -696,6 +726,9 @@ namespace TEngine } string assetObjectKey = GetCacheKey(location, packageName); + + await TryWaitingLoading(assetObjectKey); + AssetObject assetObject = m_AssetPool.Spawn(assetObjectKey); if (assetObject != null) { @@ -703,6 +736,8 @@ namespace TEngine return; } + _assetLoadingList.Add(assetObjectKey); + AssetInfo assetInfo = GetAssetInfo(location, packageName); if (!string.IsNullOrEmpty(assetInfo.Error)) @@ -730,6 +765,8 @@ namespace TEngine if (handle.AssetObject == null || handle.Status == EOperationStatus.Failed) { + _assetLoadingList.Remove(assetObjectKey); + string errorMessage = Utility.Text.Format("Can not load asset '{0}'.", location); if (loadAssetCallbacks.LoadAssetFailureCallback != null) { @@ -744,6 +781,8 @@ namespace TEngine assetObject = AssetObject.Create(assetObjectKey, handle.AssetObject, handle,this); m_AssetPool.Register(assetObject, true); + _assetLoadingList.Remove(assetObjectKey); + if (loadAssetCallbacks.LoadAssetSuccessCallback != null) { duration = Time.time - duration; @@ -774,12 +813,17 @@ namespace TEngine } string assetObjectKey = GetCacheKey(location, packageName); + + await TryWaitingLoading(assetObjectKey); + AssetObject assetObject = m_AssetPool.Spawn(assetObjectKey); if (assetObject != null) { loadAssetCallbacks.LoadAssetSuccessCallback(location, assetObject.Target, 0, userData); return; } + + _assetLoadingList.Add(assetObjectKey); AssetInfo assetInfo = GetAssetInfo(location, packageName); @@ -808,6 +852,8 @@ namespace TEngine if (handle.AssetObject == null || handle.Status == EOperationStatus.Failed) { + _assetLoadingList.Remove(assetObjectKey); + string errorMessage = Utility.Text.Format("Can not load asset '{0}'.", location); if (loadAssetCallbacks.LoadAssetFailureCallback != null) { @@ -821,6 +867,8 @@ namespace TEngine { assetObject = AssetObject.Create(assetObjectKey, handle.AssetObject, handle,this); m_AssetPool.Register(assetObject, true); + + _assetLoadingList.Remove(assetObjectKey); if (loadAssetCallbacks.LoadAssetSuccessCallback != null) { @@ -849,6 +897,13 @@ namespace TEngine } } + private async UniTask TryWaitingLoading(string assetObjectKey) + { + if (_assetLoadingList.Contains(assetObjectKey)) + { + await UniTask.WaitUntil(() => !_assetLoadingList.Contains(assetObjectKey), cancellationToken:CancellationToken); + } + } #endregion #region 资源回收