From fb06f2aa112fb3852121eaed1429062bc65cd7ac Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E4=BD=95=E5=86=A0=E5=B3=B0?= <hevinci@hotmail.com>
Date: Tue, 11 Feb 2025 17:32:31 +0800
Subject: [PATCH] update resource manager
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

UnloadAllAssetsAsync新增UnloadAllAssetsOptions参数
---
 .../Operation/UnloadAllAssetsOperation.cs     | 88 ++++++++++++------
 .../Operation/UnloadUnusedAssetsOperation.cs  |  9 +-
 .../Provider/ProviderOperation.cs             |  2 +-
 .../ResourceManager/ResourceManager.cs        | 90 ++++++++++++++-----
 .../ResourcePackage/ResourcePackage.cs        | 12 ++-
 5 files changed, 149 insertions(+), 52 deletions(-)

diff --git a/Assets/YooAsset/Runtime/ResourceManager/Operation/UnloadAllAssetsOperation.cs b/Assets/YooAsset/Runtime/ResourceManager/Operation/UnloadAllAssetsOperation.cs
index 8cb5454a..f208426d 100644
--- a/Assets/YooAsset/Runtime/ResourceManager/Operation/UnloadAllAssetsOperation.cs
+++ b/Assets/YooAsset/Runtime/ResourceManager/Operation/UnloadAllAssetsOperation.cs
@@ -3,38 +3,88 @@ using UnityEngine;
 
 namespace YooAsset
 {
+    public sealed class UnloadAllAssetsOptions
+    {
+        /// <summary>
+        /// 释放所有资源句柄,防止卸载过程中触发完成回调!
+        /// </summary>
+        public bool ReleaseAllHandles = true;
+
+        /// <summary>
+        /// 卸载过程中锁定加载操作,防止新的任务请求!
+        /// </summary>
+        public bool LockLoadOperation = true;
+    }
+
     public sealed class UnloadAllAssetsOperation : AsyncOperationBase
     {
         private enum ESteps
         {
             None,
+            CheckOptions,
+            ReleaseAll,
             AbortDownload,
             CheckLoading,
-            UnloadAll,
+            DestroyAll,
             Done,
         }
 
         private readonly ResourceManager _resManager;
+        private readonly UnloadAllAssetsOptions _options;
         private ESteps _steps = ESteps.None;
 
-        internal UnloadAllAssetsOperation(ResourceManager resourceManager)
+        internal UnloadAllAssetsOperation(ResourceManager resourceManager, UnloadAllAssetsOptions options)
         {
             _resManager = resourceManager;
+            _options = options;
         }
         internal override void InternalOnStart()
         {
-            _steps = ESteps.AbortDownload;
+            _steps = ESteps.CheckOptions;
         }
         internal override void InternalOnUpdate()
         {
             if (_steps == ESteps.None || _steps == ESteps.Done)
                 return;
 
+            if (_steps == ESteps.CheckOptions)
+            {
+                if (_options == null)
+                {
+                    _steps = ESteps.Done;
+                    Status = EOperationStatus.Failed;
+                    Error = $"{nameof(UnloadAllAssetsOptions)} is null.";
+                    return;
+                }
+
+                // 设置锁定状态
+                if (_options.LockLoadOperation)
+                    _resManager.LockLoadOperation = true;
+
+                _steps = ESteps.ReleaseAll;
+            }
+
+            if (_steps == ESteps.ReleaseAll)
+            {
+                // 清空所有场景句柄
+                _resManager.SceneHandles.Clear();
+
+                // 释放所有资源句柄
+                if (_options.ReleaseAllHandles)
+                {
+                    foreach (var provider in _resManager.ProviderDic.Values)
+                    {
+                        provider.ReleaseAllHandles();
+                    }
+                }
+
+                _steps = ESteps.AbortDownload;
+            }
+
             if (_steps == ESteps.AbortDownload)
             {
                 // 注意:终止所有下载任务
-                var loaderDic = _resManager._loaderDic;
-                foreach (var loader in loaderDic.Values)
+                foreach (var loader in _resManager.LoaderDic.Values)
                 {
                     loader.AbortDownloadOperation();
                 }
@@ -44,44 +94,32 @@ namespace YooAsset
             if (_steps == ESteps.CheckLoading)
             {
                 // 注意:等待所有任务完成
-                var providerDic = _resManager._providerDic;
-                foreach (var provider in providerDic.Values)
+                foreach (var provider in _resManager.ProviderDic.Values)
                 {
                     if (provider.IsDone == false)
                         return;
                 }
-                _steps = ESteps.UnloadAll;
+                _steps = ESteps.DestroyAll;
             }
 
-            if (_steps == ESteps.UnloadAll)
+            if (_steps == ESteps.DestroyAll)
             {
-                var loaderDic = _resManager._loaderDic;
-                var providerDic = _resManager._providerDic;
-
-                // 清空所有场景句柄
-                _resManager._sceneHandles.Clear();
-
-                // 释放所有资源句柄
-                foreach (var provider in providerDic.Values)
-                {
-                    provider.ReleaseAllHandles();
-                }
-
                 // 强制销毁资源提供者
-                foreach (var provider in providerDic.Values)
+                foreach (var provider in _resManager.ProviderDic.Values)
                 {
                     provider.DestroyProvider();
                 }
 
                 // 强制销毁文件加载器
-                foreach (var loader in loaderDic.Values)
+                foreach (var loader in _resManager.LoaderDic.Values)
                 {
                     loader.DestroyLoader();
                 }
 
                 // 清空数据
-                providerDic.Clear();
-                loaderDic.Clear();
+                _resManager.ProviderDic.Clear();
+                _resManager.LoaderDic.Clear();
+                _resManager.LockLoadOperation = false;
 
                 // 注意:调用底层接口释放所有资源
                 Resources.UnloadUnusedAssets();
diff --git a/Assets/YooAsset/Runtime/ResourceManager/Operation/UnloadUnusedAssetsOperation.cs b/Assets/YooAsset/Runtime/ResourceManager/Operation/UnloadUnusedAssetsOperation.cs
index 7ac87835..fdb2e8e4 100644
--- a/Assets/YooAsset/Runtime/ResourceManager/Operation/UnloadUnusedAssetsOperation.cs
+++ b/Assets/YooAsset/Runtime/ResourceManager/Operation/UnloadUnusedAssetsOperation.cs
@@ -31,17 +31,16 @@ namespace YooAsset
 
             if (_steps == ESteps.UnloadUnused)
             {
-                var loaderDic = _resManager._loaderDic;
-                var removeList = new List<LoadBundleFileOperation>(loaderDic.Count);
+                var removeList = new List<LoadBundleFileOperation>(_resManager.LoaderDic.Count);
 
                 // 注意:优先销毁资源提供者
-                foreach (var loader in loaderDic.Values)
+                foreach (var loader in _resManager.LoaderDic.Values)
                 {
                     loader.TryDestroyProviders();
                 }
 
                 // 获取销毁列表
-                foreach (var loader in loaderDic.Values)
+                foreach (var loader in _resManager.LoaderDic.Values)
                 {
                     if (loader.CanDestroyLoader())
                     {
@@ -54,7 +53,7 @@ namespace YooAsset
                 {
                     string bundleName = loader.LoadBundleInfo.Bundle.BundleName;
                     loader.DestroyLoader();
-                    _resManager._loaderDic.Remove(bundleName);
+                    _resManager.LoaderDic.Remove(bundleName);
                 }
 
                 // 注意:调用底层接口释放所有资源
diff --git a/Assets/YooAsset/Runtime/ResourceManager/Provider/ProviderOperation.cs b/Assets/YooAsset/Runtime/ResourceManager/Provider/ProviderOperation.cs
index cee8c42a..725e2769 100644
--- a/Assets/YooAsset/Runtime/ResourceManager/Provider/ProviderOperation.cs
+++ b/Assets/YooAsset/Runtime/ResourceManager/Provider/ProviderOperation.cs
@@ -86,7 +86,7 @@ namespace YooAsset
 
                 // 依赖资源包加载器集合
                 var dependLoaders = manager.CreateDependBundleFileLoaders(assetInfo);
-                if(dependLoaders.Count > 0)
+                if (dependLoaders.Count > 0)
                     _bundleLoaders.AddRange(dependLoaders);
 
                 // 增加引用计数
diff --git a/Assets/YooAsset/Runtime/ResourceManager/ResourceManager.cs b/Assets/YooAsset/Runtime/ResourceManager/ResourceManager.cs
index 2c942df3..53bfa6e8 100644
--- a/Assets/YooAsset/Runtime/ResourceManager/ResourceManager.cs
+++ b/Assets/YooAsset/Runtime/ResourceManager/ResourceManager.cs
@@ -9,9 +9,9 @@ namespace YooAsset
 {
     internal class ResourceManager
     {
-        internal readonly Dictionary<string, ProviderOperation> _providerDic = new Dictionary<string, ProviderOperation>(5000);
-        internal readonly Dictionary<string, LoadBundleFileOperation> _loaderDic = new Dictionary<string, LoadBundleFileOperation>(5000);
-        internal readonly List<SceneHandle> _sceneHandles = new List<SceneHandle>(100);
+        internal readonly Dictionary<string, ProviderOperation> ProviderDic = new Dictionary<string, ProviderOperation>(5000);
+        internal readonly Dictionary<string, LoadBundleFileOperation> LoaderDic = new Dictionary<string, LoadBundleFileOperation>(5000);
+        internal readonly List<SceneHandle> SceneHandles = new List<SceneHandle>(100);
         private long _sceneCreateIndex = 0;
         private IBundleQuery _bundleQuery;
 
@@ -20,6 +20,11 @@ namespace YooAsset
         /// </summary>
         public readonly string PackageName;
 
+        /// <summary>
+        /// 锁定加载操作
+        /// </summary>
+        public bool LockLoadOperation = false;
+
 
         public ResourceManager(string packageName)
         {
@@ -64,7 +69,7 @@ namespace YooAsset
                 {
                     string bundleName = mainLoader.LoadBundleInfo.Bundle.BundleName;
                     mainLoader.DestroyLoader();
-                    _loaderDic.Remove(bundleName);
+                    LoaderDic.Remove(bundleName);
                 }
             }
 
@@ -79,7 +84,7 @@ namespace YooAsset
                     {
                         string bundleName = dependLoader.LoadBundleInfo.Bundle.BundleName;
                         dependLoader.DestroyLoader();
-                        _loaderDic.Remove(bundleName);
+                        LoaderDic.Remove(bundleName);
                     }
                 }
             }
@@ -92,6 +97,15 @@ namespace YooAsset
         /// </summary>
         public SceneHandle LoadSceneAsync(AssetInfo assetInfo, LoadSceneParameters loadSceneParams, bool suspendLoad, uint priority)
         {
+            if (LockLoadOperation)
+            {
+                string error = $"The load operation locked !";
+                YooLogger.Error(error);
+                CompletedProvider completedProvider = new CompletedProvider(this, assetInfo);
+                completedProvider.SetCompletedWithError(error);
+                return completedProvider.CreateHandle<SceneHandle>();
+            }
+
             if (assetInfo.IsInvalid)
             {
                 YooLogger.Error($"Failed to load scene ! {assetInfo.Error}");
@@ -106,14 +120,14 @@ namespace YooAsset
             {
                 provider = new SceneProvider(this, providerGUID, assetInfo, loadSceneParams, suspendLoad);
                 provider.InitSpawnDebugInfo();
-                _providerDic.Add(providerGUID, provider);
+                ProviderDic.Add(providerGUID, provider);
                 OperationSystem.StartOperation(PackageName, provider);
             }
 
             provider.Priority = priority;
             var handle = provider.CreateHandle<SceneHandle>();
             handle.PackageName = PackageName;
-            _sceneHandles.Add(handle);
+            SceneHandles.Add(handle);
             return handle;
         }
 
@@ -122,6 +136,15 @@ namespace YooAsset
         /// </summary>
         public AssetHandle LoadAssetAsync(AssetInfo assetInfo, uint priority)
         {
+            if (LockLoadOperation)
+            {
+                string error = $"The load operation locked !";
+                YooLogger.Error(error);
+                CompletedProvider completedProvider = new CompletedProvider(this, assetInfo);
+                completedProvider.SetCompletedWithError(error);
+                return completedProvider.CreateHandle<AssetHandle>();
+            }
+
             if (assetInfo.IsInvalid)
             {
                 YooLogger.Error($"Failed to load asset ! {assetInfo.Error}");
@@ -136,7 +159,7 @@ namespace YooAsset
             {
                 provider = new AssetProvider(this, providerGUID, assetInfo);
                 provider.InitSpawnDebugInfo();
-                _providerDic.Add(providerGUID, provider);
+                ProviderDic.Add(providerGUID, provider);
                 OperationSystem.StartOperation(PackageName, provider);
             }
 
@@ -149,6 +172,15 @@ namespace YooAsset
         /// </summary>
         public SubAssetsHandle LoadSubAssetsAsync(AssetInfo assetInfo, uint priority)
         {
+            if (LockLoadOperation)
+            {
+                string error = $"The load operation locked !";
+                YooLogger.Error(error);
+                CompletedProvider completedProvider = new CompletedProvider(this, assetInfo);
+                completedProvider.SetCompletedWithError(error);
+                return completedProvider.CreateHandle<SubAssetsHandle>();
+            }
+
             if (assetInfo.IsInvalid)
             {
                 YooLogger.Error($"Failed to load sub assets ! {assetInfo.Error}");
@@ -163,7 +195,7 @@ namespace YooAsset
             {
                 provider = new SubAssetsProvider(this, providerGUID, assetInfo);
                 provider.InitSpawnDebugInfo();
-                _providerDic.Add(providerGUID, provider);
+                ProviderDic.Add(providerGUID, provider);
                 OperationSystem.StartOperation(PackageName, provider);
             }
 
@@ -176,6 +208,15 @@ namespace YooAsset
         /// </summary>
         public AllAssetsHandle LoadAllAssetsAsync(AssetInfo assetInfo, uint priority)
         {
+            if (LockLoadOperation)
+            {
+                string error = $"The load operation locked !";
+                YooLogger.Error(error);
+                CompletedProvider completedProvider = new CompletedProvider(this, assetInfo);
+                completedProvider.SetCompletedWithError(error);
+                return completedProvider.CreateHandle<AllAssetsHandle>();
+            }
+
             if (assetInfo.IsInvalid)
             {
                 YooLogger.Error($"Failed to load all assets ! {assetInfo.Error}");
@@ -190,7 +231,7 @@ namespace YooAsset
             {
                 provider = new AllAssetsProvider(this, providerGUID, assetInfo);
                 provider.InitSpawnDebugInfo();
-                _providerDic.Add(providerGUID, provider);
+                ProviderDic.Add(providerGUID, provider);
                 OperationSystem.StartOperation(PackageName, provider);
             }
 
@@ -203,6 +244,15 @@ namespace YooAsset
         /// </summary>
         public RawFileHandle LoadRawFileAsync(AssetInfo assetInfo, uint priority)
         {
+            if (LockLoadOperation)
+            {
+                string error = $"The load operation locked !";
+                YooLogger.Error(error);
+                CompletedProvider completedProvider = new CompletedProvider(this, assetInfo);
+                completedProvider.SetCompletedWithError(error);
+                return completedProvider.CreateHandle<RawFileHandle>();
+            }
+
             if (assetInfo.IsInvalid)
             {
                 YooLogger.Error($"Failed to load raw file ! {assetInfo.Error}");
@@ -217,7 +267,7 @@ namespace YooAsset
             {
                 provider = new RawFileProvider(this, providerGUID, assetInfo);
                 provider.InitSpawnDebugInfo();
-                _providerDic.Add(providerGUID, provider);
+                ProviderDic.Add(providerGUID, provider);
                 OperationSystem.StartOperation(PackageName, provider);
             }
 
@@ -245,12 +295,12 @@ namespace YooAsset
         {
             foreach (var provider in removeList)
             {
-                _providerDic.Remove(provider.ProviderGUID);
+                ProviderDic.Remove(provider.ProviderGUID);
             }
         }
         internal bool HasAnyLoader()
         {
-            return _loaderDic.Count > 0;
+            return LoaderDic.Count > 0;
         }
 
         private LoadBundleFileOperation CreateBundleFileLoaderInternal(BundleInfo bundleInfo)
@@ -264,19 +314,19 @@ namespace YooAsset
             // 新增下载需求
             loaderOperation = new LoadBundleFileOperation(this, bundleInfo);
             OperationSystem.StartOperation(PackageName, loaderOperation);
-            _loaderDic.Add(bundleName, loaderOperation);
+            LoaderDic.Add(bundleName, loaderOperation);
             return loaderOperation;
         }
         private LoadBundleFileOperation TryGetBundleFileLoader(string bundleName)
         {
-            if (_loaderDic.TryGetValue(bundleName, out LoadBundleFileOperation value))
+            if (LoaderDic.TryGetValue(bundleName, out LoadBundleFileOperation value))
                 return value;
             else
                 return null;
         }
         private ProviderOperation TryGetAssetProvider(string providerGUID)
         {
-            if (_providerDic.TryGetValue(providerGUID, out ProviderOperation value))
+            if (ProviderDic.TryGetValue(providerGUID, out ProviderOperation value))
                 return value;
             else
                 return null;
@@ -284,7 +334,7 @@ namespace YooAsset
         private void OnSceneUnloaded(Scene scene)
         {
             List<SceneHandle> removeList = new List<SceneHandle>();
-            foreach (var sceneHandle in _sceneHandles)
+            foreach (var sceneHandle in SceneHandles)
             {
                 if (sceneHandle.IsValid)
                 {
@@ -297,15 +347,15 @@ namespace YooAsset
             }
             foreach (var sceneHandle in removeList)
             {
-                _sceneHandles.Remove(sceneHandle);
+                SceneHandles.Remove(sceneHandle);
             }
         }
 
         #region 调试信息
         internal List<DebugProviderInfo> GetDebugReportInfos()
         {
-            List<DebugProviderInfo> result = new List<DebugProviderInfo>(_providerDic.Count);
-            foreach (var provider in _providerDic.Values)
+            List<DebugProviderInfo> result = new List<DebugProviderInfo>(ProviderDic.Count);
+            foreach (var provider in ProviderDic.Values)
             {
                 DebugProviderInfo providerInfo = new DebugProviderInfo();
                 providerInfo.AssetPath = provider.MainAssetInfo.AssetPath;
diff --git a/Assets/YooAsset/Runtime/ResourcePackage/ResourcePackage.cs b/Assets/YooAsset/Runtime/ResourcePackage/ResourcePackage.cs
index a8a7de7e..591444b8 100644
--- a/Assets/YooAsset/Runtime/ResourcePackage/ResourcePackage.cs
+++ b/Assets/YooAsset/Runtime/ResourcePackage/ResourcePackage.cs
@@ -318,9 +318,19 @@ namespace YooAsset
         /// 强制回收所有资源
         /// </summary>
         public UnloadAllAssetsOperation UnloadAllAssetsAsync()
+        {
+            var options = new UnloadAllAssetsOptions();
+            return UnloadAllAssetsAsync(options);
+        }
+
+        /// <summary>
+        /// 强制回收所有资源
+        /// </summary>
+        /// <param name="options">卸载选项</param>
+        public UnloadAllAssetsOperation UnloadAllAssetsAsync(UnloadAllAssetsOptions options)
         {
             DebugCheckInitialize();
-            var operation = new UnloadAllAssetsOperation(_resourceManager);
+            var operation = new UnloadAllAssetsOperation(_resourceManager, options);
             OperationSystem.StartOperation(PackageName, operation);
             return operation;
         }