From a3f689d815d6ed215e38fb8f8803c15de4961f6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BD=95=E5=86=A0=E5=B3=B0?= Date: Mon, 12 Jan 2026 11:09:27 +0800 Subject: [PATCH] =?UTF-8?q?refactor=20:=20=E9=87=8D=E6=9E=84=E5=BC=82?= =?UTF-8?q?=E6=AD=A5=E6=93=8D=E4=BD=9C=E6=A8=A1=E5=9D=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../AssetBundleLoadAllAssetsOperation.cs | 9 +- .../AssetBundleLoadAssetOperation.cs | 9 +- .../AssetBundleLoadSceneOperation.cs | 2 +- .../AssetBundleLoadSubAssetsOperation.cs | 9 +- .../VirtualBundleLoadAllAssetsOperation.cs | 9 +- .../VirtualBundleLoadAssetOperation.cs | 9 +- .../VirtualBundleLoadSceneOperation.cs | 2 +- .../VirtualBundleLoadSubAssetsOperation.cs | 9 +- .../Operation/DBFSLoadBundleOperation.cs | 142 +++++++++++- .../Operation/DCFSLoadBundleOperation.cs | 18 +- .../DownloadPackageBundleOperation.cs | 9 +- .../DownloadAndCacheLocalFileOperation.cs | 21 +- .../DownloadAndCacheRemoteFileOperation.cs | 2 +- .../Scheduler/DownloadSchedulerOperation.cs | 21 +- .../internal/VerifyTempFileOperation.cs | 12 +- .../Operation/DEFSLoadBundleOperation.cs | 9 +- .../Operation/DWRFSLoadBundleOperation.cs | 2 +- .../Operation/DWSFSLoadBundleOperation.cs | 2 +- .../OperationSystem/AsyncOperationBase.cs | 81 +++++-- .../OperationSystem/OperationScheduler.cs | 33 ++- .../OperationSystem/OperationSystem.cs | 65 +----- .../Runtime/OperationSystem/README.md | 212 ++++-------------- .../Operation/InstantiateOperation.cs | 16 +- .../Internal/LoadBundleFileOperation.cs | 9 +- .../Operation/UnloadUnusedAssetsOperation.cs | 9 +- .../Provider/ProviderOperation.cs | 9 +- .../ResourcePackage/EBuildBundleType.cs | 5 + .../Internal/DeserializeManifestOperation.cs | 9 +- .../ResourcePackage/ResourcePackage.cs | 2 +- Assets/YooAsset/Runtime/YooAssets.cs | 2 +- 30 files changed, 315 insertions(+), 433 deletions(-) diff --git a/Assets/YooAsset/Runtime/FileSystem/BundleResult/AssetBundleResult/Operation/AssetBundleLoadAllAssetsOperation.cs b/Assets/YooAsset/Runtime/FileSystem/BundleResult/AssetBundleResult/Operation/AssetBundleLoadAllAssetsOperation.cs index f5bd7f35..f508718c 100644 --- a/Assets/YooAsset/Runtime/FileSystem/BundleResult/AssetBundleResult/Operation/AssetBundleLoadAllAssetsOperation.cs +++ b/Assets/YooAsset/Runtime/FileSystem/BundleResult/AssetBundleResult/Operation/AssetBundleLoadAllAssetsOperation.cs @@ -108,14 +108,7 @@ namespace YooAsset } internal override void InternalWaitForAsyncComplete() { - while (true) - { - if (ExecuteWhileDone()) - { - _steps = ESteps.Done; - break; - } - } + RunBatchExecution(); } } } \ No newline at end of file diff --git a/Assets/YooAsset/Runtime/FileSystem/BundleResult/AssetBundleResult/Operation/AssetBundleLoadAssetOperation.cs b/Assets/YooAsset/Runtime/FileSystem/BundleResult/AssetBundleResult/Operation/AssetBundleLoadAssetOperation.cs index 78cc5bfc..50cfe93a 100644 --- a/Assets/YooAsset/Runtime/FileSystem/BundleResult/AssetBundleResult/Operation/AssetBundleLoadAssetOperation.cs +++ b/Assets/YooAsset/Runtime/FileSystem/BundleResult/AssetBundleResult/Operation/AssetBundleLoadAssetOperation.cs @@ -108,14 +108,7 @@ namespace YooAsset } internal override void InternalWaitForAsyncComplete() { - while (true) - { - if (ExecuteWhileDone()) - { - _steps = ESteps.Done; - break; - } - } + RunBatchExecution(); } } } \ No newline at end of file diff --git a/Assets/YooAsset/Runtime/FileSystem/BundleResult/AssetBundleResult/Operation/AssetBundleLoadSceneOperation.cs b/Assets/YooAsset/Runtime/FileSystem/BundleResult/AssetBundleResult/Operation/AssetBundleLoadSceneOperation.cs index a7ef41a2..6b68472f 100644 --- a/Assets/YooAsset/Runtime/FileSystem/BundleResult/AssetBundleResult/Operation/AssetBundleLoadSceneOperation.cs +++ b/Assets/YooAsset/Runtime/FileSystem/BundleResult/AssetBundleResult/Operation/AssetBundleLoadSceneOperation.cs @@ -107,7 +107,7 @@ namespace YooAsset internal override void InternalWaitForAsyncComplete() { //注意:场景加载不支持异步转同步,为了支持同步加载方法需要实现该方法! - InternalUpdate(); + RunOnceExecution(); } public override void UnSuspendLoad() { diff --git a/Assets/YooAsset/Runtime/FileSystem/BundleResult/AssetBundleResult/Operation/AssetBundleLoadSubAssetsOperation.cs b/Assets/YooAsset/Runtime/FileSystem/BundleResult/AssetBundleResult/Operation/AssetBundleLoadSubAssetsOperation.cs index c3b9ccae..0cd92e8a 100644 --- a/Assets/YooAsset/Runtime/FileSystem/BundleResult/AssetBundleResult/Operation/AssetBundleLoadSubAssetsOperation.cs +++ b/Assets/YooAsset/Runtime/FileSystem/BundleResult/AssetBundleResult/Operation/AssetBundleLoadSubAssetsOperation.cs @@ -108,14 +108,7 @@ namespace YooAsset } internal override void InternalWaitForAsyncComplete() { - while (true) - { - if (ExecuteWhileDone()) - { - _steps = ESteps.Done; - break; - } - } + RunBatchExecution(); } } } \ No newline at end of file diff --git a/Assets/YooAsset/Runtime/FileSystem/BundleResult/VirtualBundleResult/Operation/VirtualBundleLoadAllAssetsOperation.cs b/Assets/YooAsset/Runtime/FileSystem/BundleResult/VirtualBundleResult/Operation/VirtualBundleLoadAllAssetsOperation.cs index 3b9a0a14..12f9de74 100644 --- a/Assets/YooAsset/Runtime/FileSystem/BundleResult/VirtualBundleResult/Operation/VirtualBundleLoadAllAssetsOperation.cs +++ b/Assets/YooAsset/Runtime/FileSystem/BundleResult/VirtualBundleResult/Operation/VirtualBundleLoadAllAssetsOperation.cs @@ -109,14 +109,7 @@ namespace YooAsset } internal override void InternalWaitForAsyncComplete() { - while (true) - { - if (ExecuteWhileDone()) - { - _steps = ESteps.Done; - break; - } - } + RunBatchExecution(); } } } \ No newline at end of file diff --git a/Assets/YooAsset/Runtime/FileSystem/BundleResult/VirtualBundleResult/Operation/VirtualBundleLoadAssetOperation.cs b/Assets/YooAsset/Runtime/FileSystem/BundleResult/VirtualBundleResult/Operation/VirtualBundleLoadAssetOperation.cs index 64d4ae34..9efe0345 100644 --- a/Assets/YooAsset/Runtime/FileSystem/BundleResult/VirtualBundleResult/Operation/VirtualBundleLoadAssetOperation.cs +++ b/Assets/YooAsset/Runtime/FileSystem/BundleResult/VirtualBundleResult/Operation/VirtualBundleLoadAssetOperation.cs @@ -88,14 +88,7 @@ namespace YooAsset } internal override void InternalWaitForAsyncComplete() { - while (true) - { - if (ExecuteWhileDone()) - { - _steps = ESteps.Done; - break; - } - } + RunBatchExecution(); } } } \ No newline at end of file diff --git a/Assets/YooAsset/Runtime/FileSystem/BundleResult/VirtualBundleResult/Operation/VirtualBundleLoadSceneOperation.cs b/Assets/YooAsset/Runtime/FileSystem/BundleResult/VirtualBundleResult/Operation/VirtualBundleLoadSceneOperation.cs index cdbe006c..6ee0198e 100644 --- a/Assets/YooAsset/Runtime/FileSystem/BundleResult/VirtualBundleResult/Operation/VirtualBundleLoadSceneOperation.cs +++ b/Assets/YooAsset/Runtime/FileSystem/BundleResult/VirtualBundleResult/Operation/VirtualBundleLoadSceneOperation.cs @@ -113,7 +113,7 @@ namespace YooAsset internal override void InternalWaitForAsyncComplete() { //注意:场景加载不支持异步转同步,为了支持同步加载方法需要实现该方法! - InternalUpdate(); + RunOnceExecution(); } public override void UnSuspendLoad() { diff --git a/Assets/YooAsset/Runtime/FileSystem/BundleResult/VirtualBundleResult/Operation/VirtualBundleLoadSubAssetsOperation.cs b/Assets/YooAsset/Runtime/FileSystem/BundleResult/VirtualBundleResult/Operation/VirtualBundleLoadSubAssetsOperation.cs index 587c3a42..d2d585d1 100644 --- a/Assets/YooAsset/Runtime/FileSystem/BundleResult/VirtualBundleResult/Operation/VirtualBundleLoadSubAssetsOperation.cs +++ b/Assets/YooAsset/Runtime/FileSystem/BundleResult/VirtualBundleResult/Operation/VirtualBundleLoadSubAssetsOperation.cs @@ -100,14 +100,7 @@ namespace YooAsset } internal override void InternalWaitForAsyncComplete() { - while (true) - { - if (ExecuteWhileDone()) - { - _steps = ESteps.Done; - break; - } - } + RunBatchExecution(); } } } \ No newline at end of file diff --git a/Assets/YooAsset/Runtime/FileSystem/DefaultBuildinFileSystem/Operation/DBFSLoadBundleOperation.cs b/Assets/YooAsset/Runtime/FileSystem/DefaultBuildinFileSystem/Operation/DBFSLoadBundleOperation.cs index 9c363233..db943918 100644 --- a/Assets/YooAsset/Runtime/FileSystem/DefaultBuildinFileSystem/Operation/DBFSLoadBundleOperation.cs +++ b/Assets/YooAsset/Runtime/FileSystem/DefaultBuildinFileSystem/Operation/DBFSLoadBundleOperation.cs @@ -131,14 +131,7 @@ namespace YooAsset } internal override void InternalWaitForAsyncComplete() { - while (true) - { - if (ExecuteWhileDone()) - { - _steps = ESteps.Done; - break; - } - } + RunBatchExecution(); } } @@ -204,14 +197,141 @@ namespace YooAsset } internal override void InternalWaitForAsyncComplete() { - while (true) + RunBatchExecution(); + } + } + +#if TUANJIE_1_7_OR_NEWER + /// + /// 加载团结文件 + /// + internal class DBFSLoadInstantBundleOperation : FSLoadBundleOperation + { + private enum ESteps + { + None, + LoadInstantBundle, + CheckResult, + Done, + } + + private readonly DefaultBuildinFileSystem _fileSystem; + private readonly PackageBundle _bundle; + private AssetBundleCreateRequest _createRequest; + private AssetBundle _assetBundle; + private Stream _managedStream; + private ESteps _steps = ESteps.None; + + + internal DBFSLoadInstantBundleOperation(DefaultBuildinFileSystem fileSystem, PackageBundle bundle) + { + _fileSystem = fileSystem; + _bundle = bundle; + } + internal override void InternalStart() + { + DownloadProgress = 1f; + DownloadedBytes = _bundle.FileSize; + _steps = ESteps.LoadInstantBundle; + } + internal override void InternalUpdate() + { + if (_steps == ESteps.None || _steps == ESteps.Done) + return; + + if (_steps == ESteps.LoadInstantBundle) { - if (ExecuteWhileDone()) + if (_bundle.Encrypted) + { + if (_fileSystem.DecryptionServices == null) + { + _steps = ESteps.Done; + Status = EOperationStatus.Failed; + Error = $"The {nameof(IDecryptionServices)} is null !"; + YooLogger.Error(Error); + return; + } + } + + if (IsWaitForAsyncComplete) + { + if (_bundle.Encrypted) + { + var decryptResult = _fileSystem.LoadEncryptedAssetBundle(_bundle); + _assetBundle = decryptResult.Result; + _managedStream = decryptResult.ManagedStream; + } + else + { + string filePath = _fileSystem.GetBuildinFileLoadPath(_bundle); + _assetBundle = AssetBundle.LoadFromFile(filePath); + } + } + else + { + if (_bundle.Encrypted) + { + var decryptResult = _fileSystem.LoadEncryptedAssetBundleAsync(_bundle); + _createRequest = decryptResult.CreateRequest; + _managedStream = decryptResult.ManagedStream; + } + else + { + string filePath = _fileSystem.GetBuildinFileLoadPath(_bundle); + _createRequest = AssetBundle.LoadFromFileAsync(filePath); + } + } + + _steps = ESteps.CheckResult; + } + + if (_steps == ESteps.CheckResult) + { + if (_createRequest != null) + { + if (IsWaitForAsyncComplete) + { + // 强制挂起主线程(注意:该操作会很耗时) + YooLogger.Warning("Suspend the main thread to load unity bundle."); + _assetBundle = _createRequest.assetBundle; + } + else + { + if (_createRequest.isDone == false) + return; + _assetBundle = _createRequest.assetBundle; + } + } + + if (_assetBundle == null) + { + if (_bundle.Encrypted) + { + _steps = ESteps.Done; + Status = EOperationStatus.Failed; + Error = $"Failed to load encrypted buildin asset bundle file : {_bundle.BundleName}"; + YooLogger.Error(Error); + } + else + { + _steps = ESteps.Done; + Status = EOperationStatus.Failed; + Error = $"Failed to load buildin asset bundle file : {_bundle.BundleName}"; + YooLogger.Error(Error); + } + } + else { _steps = ESteps.Done; - break; + Result = new AssetBundleResult(_fileSystem, _bundle, _assetBundle, _managedStream); + Status = EOperationStatus.Succeed; } } } + internal override void InternalWaitForAsyncComplete() + { + RunBatchExecution(); + } } +#endif } \ No newline at end of file diff --git a/Assets/YooAsset/Runtime/FileSystem/DefaultCacheFileSystem/Operation/DCFSLoadBundleOperation.cs b/Assets/YooAsset/Runtime/FileSystem/DefaultCacheFileSystem/Operation/DCFSLoadBundleOperation.cs index e5d1ee50..2c4331a9 100644 --- a/Assets/YooAsset/Runtime/FileSystem/DefaultCacheFileSystem/Operation/DCFSLoadBundleOperation.cs +++ b/Assets/YooAsset/Runtime/FileSystem/DefaultCacheFileSystem/Operation/DCFSLoadBundleOperation.cs @@ -262,14 +262,7 @@ namespace YooAsset } internal override void InternalWaitForAsyncComplete() { - while (true) - { - if (ExecuteWhileDone()) - { - _steps = ESteps.Done; - break; - } - } + RunBatchExecution(); } } @@ -419,14 +412,7 @@ namespace YooAsset } internal override void InternalWaitForAsyncComplete() { - while (true) - { - if (ExecuteWhileDone()) - { - _steps = ESteps.Done; - break; - } - } + RunBatchExecution(); } } } \ No newline at end of file diff --git a/Assets/YooAsset/Runtime/FileSystem/DefaultCacheFileSystem/Operation/internal/DownloadPackageBundleOperation.cs b/Assets/YooAsset/Runtime/FileSystem/DefaultCacheFileSystem/Operation/internal/DownloadPackageBundleOperation.cs index 3f47bc22..e9126d30 100644 --- a/Assets/YooAsset/Runtime/FileSystem/DefaultCacheFileSystem/Operation/internal/DownloadPackageBundleOperation.cs +++ b/Assets/YooAsset/Runtime/FileSystem/DefaultCacheFileSystem/Operation/internal/DownloadPackageBundleOperation.cs @@ -124,14 +124,7 @@ namespace YooAsset } internal override void InternalWaitForAsyncComplete() { - while (true) - { - if (ExecuteWhileDone()) - { - _steps = ESteps.Done; - break; - } - } + RunBatchExecution(); } internal override void InternalAbort() { diff --git a/Assets/YooAsset/Runtime/FileSystem/DefaultCacheFileSystem/Operation/internal/Scheduler/DownloadAndCacheLocalFileOperation.cs b/Assets/YooAsset/Runtime/FileSystem/DefaultCacheFileSystem/Operation/internal/Scheduler/DownloadAndCacheLocalFileOperation.cs index c8cbfed1..c02d37aa 100644 --- a/Assets/YooAsset/Runtime/FileSystem/DefaultCacheFileSystem/Operation/internal/Scheduler/DownloadAndCacheLocalFileOperation.cs +++ b/Assets/YooAsset/Runtime/FileSystem/DefaultCacheFileSystem/Operation/internal/Scheduler/DownloadAndCacheLocalFileOperation.cs @@ -98,6 +98,10 @@ namespace YooAsset // 检测下载结果 if (_steps == ESteps.CheckRequest) { + //TODO 更新下载后台,防止无限挂起 + if (IsWaitForAsyncComplete) + _fileSystem.DownloadBackend.Update(); + DownloadProgress = _request.DownloadProgress; DownloadedBytes = _request.DownloadedBytes; Progress = DownloadProgress; @@ -177,23 +181,12 @@ namespace YooAsset internal override void InternalAbort() { if (_request != null) - _request.AbortRequest(); + _request.Dispose(); } internal override void InternalWaitForAsyncComplete() { - while (true) - { - //TODO 更新下载后台,防止无限挂起 - _fileSystem.DownloadBackend.Update(); - - //TODO 等待导入或解压本地文件完毕,该操作会挂起主线程! - InternalUpdate(); - if (IsDone) - break; - - //TODO 短暂休眠避免完全卡死 - System.Threading.Thread.Sleep(1); - } + //TODO 等待导入或解压本地文件完毕,该操作会挂起主线程! + RunUntilCompletion(); } } } \ No newline at end of file diff --git a/Assets/YooAsset/Runtime/FileSystem/DefaultCacheFileSystem/Operation/internal/Scheduler/DownloadAndCacheRemoteFileOperation.cs b/Assets/YooAsset/Runtime/FileSystem/DefaultCacheFileSystem/Operation/internal/Scheduler/DownloadAndCacheRemoteFileOperation.cs index 563c0578..391038e7 100644 --- a/Assets/YooAsset/Runtime/FileSystem/DefaultCacheFileSystem/Operation/internal/Scheduler/DownloadAndCacheRemoteFileOperation.cs +++ b/Assets/YooAsset/Runtime/FileSystem/DefaultCacheFileSystem/Operation/internal/Scheduler/DownloadAndCacheRemoteFileOperation.cs @@ -144,7 +144,7 @@ namespace YooAsset internal override void InternalAbort() { if (_request != null) - _request.AbortRequest(); + _request.Dispose(); } internal override void InternalWaitForAsyncComplete() { diff --git a/Assets/YooAsset/Runtime/FileSystem/DefaultCacheFileSystem/Operation/internal/Scheduler/DownloadSchedulerOperation.cs b/Assets/YooAsset/Runtime/FileSystem/DefaultCacheFileSystem/Operation/internal/Scheduler/DownloadSchedulerOperation.cs index 6f6ff833..2107c72a 100644 --- a/Assets/YooAsset/Runtime/FileSystem/DefaultCacheFileSystem/Operation/internal/Scheduler/DownloadSchedulerOperation.cs +++ b/Assets/YooAsset/Runtime/FileSystem/DefaultCacheFileSystem/Operation/internal/Scheduler/DownloadSchedulerOperation.cs @@ -119,23 +119,16 @@ namespace YooAsset } /// - /// 中止所有下载任务 - /// - public void AbortAll() - { - foreach (var valuePair in _downloaders) - { - valuePair.Value.AbortOperation(); - } - _downloaders.Clear(); - } - - /// - /// 释放资源 + /// 释放下载资源 /// public void Dispose() { - AbortAll(); + foreach (var valuePair in _downloaders) + { + var operation = valuePair.Value; + operation.AbortOperation(); + } + _downloaders.Clear(); } /// diff --git a/Assets/YooAsset/Runtime/FileSystem/DefaultCacheFileSystem/Operation/internal/VerifyTempFileOperation.cs b/Assets/YooAsset/Runtime/FileSystem/DefaultCacheFileSystem/Operation/internal/VerifyTempFileOperation.cs index b88aa886..6477a277 100644 --- a/Assets/YooAsset/Runtime/FileSystem/DefaultCacheFileSystem/Operation/internal/VerifyTempFileOperation.cs +++ b/Assets/YooAsset/Runtime/FileSystem/DefaultCacheFileSystem/Operation/internal/VerifyTempFileOperation.cs @@ -69,16 +69,8 @@ namespace YooAsset } internal override void InternalWaitForAsyncComplete() { - while (true) - { - //TODO 等待子线程验证文件完毕,该操作会挂起主线程! - InternalUpdate(); - if (IsDone) - break; - - //TODO 短暂休眠避免完全卡死 - System.Threading.Thread.Sleep(1); - } + //TODO 等待子线程验证文件完毕,该操作会挂起主线程! + RunUntilCompletion(); } private void VerifyInThread(object obj) diff --git a/Assets/YooAsset/Runtime/FileSystem/DefaultEditorFileSystem/Operation/DEFSLoadBundleOperation.cs b/Assets/YooAsset/Runtime/FileSystem/DefaultEditorFileSystem/Operation/DEFSLoadBundleOperation.cs index 65685ce9..bee45a28 100644 --- a/Assets/YooAsset/Runtime/FileSystem/DefaultEditorFileSystem/Operation/DEFSLoadBundleOperation.cs +++ b/Assets/YooAsset/Runtime/FileSystem/DefaultEditorFileSystem/Operation/DEFSLoadBundleOperation.cs @@ -142,14 +142,7 @@ namespace YooAsset } internal override void InternalWaitForAsyncComplete() { - while (true) - { - if (ExecuteWhileDone()) - { - _steps = ESteps.Done; - break; - } - } + RunBatchExecution(); } } } \ No newline at end of file diff --git a/Assets/YooAsset/Runtime/FileSystem/DefaultWebRemoteFileSystem/Operation/DWRFSLoadBundleOperation.cs b/Assets/YooAsset/Runtime/FileSystem/DefaultWebRemoteFileSystem/Operation/DWRFSLoadBundleOperation.cs index b16c1aad..a09f0438 100644 --- a/Assets/YooAsset/Runtime/FileSystem/DefaultWebRemoteFileSystem/Operation/DWRFSLoadBundleOperation.cs +++ b/Assets/YooAsset/Runtime/FileSystem/DefaultWebRemoteFileSystem/Operation/DWRFSLoadBundleOperation.cs @@ -91,7 +91,7 @@ namespace YooAsset _steps = ESteps.Done; Status = EOperationStatus.Failed; Error = "WebGL platform not support sync load method !"; - UnityEngine.Debug.LogError(Error); + YooLogger.Error(Error); } } } diff --git a/Assets/YooAsset/Runtime/FileSystem/DefaultWebServerFileSystem/Operation/DWSFSLoadBundleOperation.cs b/Assets/YooAsset/Runtime/FileSystem/DefaultWebServerFileSystem/Operation/DWSFSLoadBundleOperation.cs index be4b003b..0a4c21b6 100644 --- a/Assets/YooAsset/Runtime/FileSystem/DefaultWebServerFileSystem/Operation/DWSFSLoadBundleOperation.cs +++ b/Assets/YooAsset/Runtime/FileSystem/DefaultWebServerFileSystem/Operation/DWSFSLoadBundleOperation.cs @@ -91,7 +91,7 @@ namespace YooAsset _steps = ESteps.Done; Status = EOperationStatus.Failed; Error = "WebGL platform not support sync load method !"; - UnityEngine.Debug.LogError(Error); + YooLogger.Error(Error); } } } diff --git a/Assets/YooAsset/Runtime/OperationSystem/AsyncOperationBase.cs b/Assets/YooAsset/Runtime/OperationSystem/AsyncOperationBase.cs index 016eaa5b..3cef6e73 100644 --- a/Assets/YooAsset/Runtime/OperationSystem/AsyncOperationBase.cs +++ b/Assets/YooAsset/Runtime/OperationSystem/AsyncOperationBase.cs @@ -10,7 +10,7 @@ namespace YooAsset { private List _childs; private Action _callback; - private int _whileFrame = 1000; + private uint _priority = 0; /// /// 等待异步执行完成 @@ -35,10 +35,28 @@ namespace YooAsset } } + /// + /// 标记脏(用于调度器检测并重排) + /// + internal bool IsDirty { set; get; } = false; + /// /// 任务优先级 /// - public uint Priority { set; get; } = 0; + public uint Priority + { + set + { + if (_priority == value) + return; + _priority = value; + IsDirty = true; + } + get + { + return _priority; + } + } /// /// 任务状态 @@ -122,7 +140,7 @@ namespace YooAsset } internal virtual void InternalWaitForAsyncComplete() { - throw new System.NotImplementedException(this.GetType().Name); + throw new YooInternalException($"InternalWaitForAsyncComplete() not implemented : {this.GetType().Name}"); } internal virtual string InternalGetDesc() { @@ -259,25 +277,63 @@ namespace YooAsset } /// - /// 执行While循环 + /// 执行一次更新逻辑 /// - protected bool ExecuteWhileDone() + protected void RunOnceExecution() { - if (IsDone == false) + if (IsDone) + return; + + UpdateOperation(); + } + + /// + /// 批量执行一定次数的更新逻辑 + /// + /// 次数 + protected void RunBatchExecution(int count = 1000) + { + if (IsDone) + return; + + int runCount = count; + while (true) { // 执行更新逻辑 - InternalUpdate(); + UpdateOperation(); + if (IsDone) + break; // 当执行次数用完时 - _whileFrame--; - if (_whileFrame <= 0) + runCount--; + if (runCount <= 0) { Status = EOperationStatus.Failed; Error = $"Operation {this.GetType().Name} failed to wait for async complete !"; YooLogger.Error(Error); + break; } } - return IsDone; + } + + /// + /// 无限次数的执行更新逻辑,直到任务完成 + /// + /// 休眠时长 + protected void RunUntilCompletion(int sleepMS = 1) + { + if (IsDone) + return; + + while (true) + { + UpdateOperation(); + if (IsDone) + break; + + // 注意: 短暂休眠避免完全占用CPU资源 + System.Threading.Thread.Sleep(sleepMS); + } } /// @@ -299,11 +355,6 @@ namespace YooAsset { IsWaitForAsyncComplete = true; InternalWaitForAsyncComplete(); - -#if UNITY_EDITOR - if (IsDone == false) - throw new YooInternalException($"WaitForAsyncComplete() must complete operation: {this.GetType().Name}"); -#endif } } diff --git a/Assets/YooAsset/Runtime/OperationSystem/OperationScheduler.cs b/Assets/YooAsset/Runtime/OperationSystem/OperationScheduler.cs index 51463577..c12ac0de 100644 --- a/Assets/YooAsset/Runtime/OperationSystem/OperationScheduler.cs +++ b/Assets/YooAsset/Runtime/OperationSystem/OperationScheduler.cs @@ -41,9 +41,6 @@ namespace YooAsset { _newList.Add(operation); operation.StartOperation(); - - // 通知开始回调 - OperationSystem.InvokeStartCallback(PackageName, operation); } /// @@ -58,31 +55,29 @@ namespace YooAsset if (operation.IsFinish) { _operations.RemoveAt(i); - - // 通知完成回调 - OperationSystem.InvokeFinishCallback(PackageName, operation); } } // 添加新增的异步操作 if (_newList.Count > 0) { - bool sorting = false; - foreach (var operation in _newList) - { - if (operation.Priority > 0) - { - sorting = true; - break; - } - } - _operations.AddRange(_newList); _newList.Clear(); + } - // 重新排序优先级 - if (sorting) - _operations.Sort(); + // 检测是否需要执行排序 + bool isDirty = false; + foreach (var operation in _operations) + { + if (operation.IsDirty) + { + operation.IsDirty = false; + isDirty = true; + } + } + if (isDirty) + { + _operations.Sort(); } // 更新进行中的异步操作 diff --git a/Assets/YooAsset/Runtime/OperationSystem/OperationSystem.cs b/Assets/YooAsset/Runtime/OperationSystem/OperationSystem.cs index a5964487..b507cea5 100644 --- a/Assets/YooAsset/Runtime/OperationSystem/OperationSystem.cs +++ b/Assets/YooAsset/Runtime/OperationSystem/OperationSystem.cs @@ -16,16 +16,14 @@ namespace YooAsset #endif // 全局调度器名称 - public const string GLOBAL_SCHEDULER_NAME = ""; + public const string GLOBAL_SCHEDULER_NAME = "YOOASSET_GLOBAL_SCHEDULER"; private static readonly Dictionary _schedulerDic = new Dictionary(100); private static readonly List _schedulerList = new List(100); + private static bool _isInitialize = false; private static bool _schedulerListDirty = false; private static int _createIndex = 0; - private static Action _startCallback = null; - private static Action _finishCallback = null; - // 计时器相关 private static Stopwatch _watch; private static long _frameTime; @@ -59,6 +57,7 @@ namespace YooAsset /// public static void Initialize() { + _isInitialize = true; _watch = Stopwatch.StartNew(); // 创建全局调度器 @@ -70,6 +69,9 @@ namespace YooAsset /// public static void Update() { + if (_isInitialize == false) + return; + // 重新排序调度器 if (_schedulerListDirty) { @@ -104,9 +106,8 @@ namespace YooAsset _schedulerList.Clear(); _schedulerListDirty = false; _createIndex = 0; + _isInitialize = false; - _startCallback = null; - _finishCallback = null; _watch = null; _frameTime = 0; MaxTimeSlice = long.MaxValue; @@ -115,7 +116,7 @@ namespace YooAsset /// /// 创建包裹调度器 /// - internal static void CreatePackageScheduler(string packageName, int priority) + public static void CreatePackageScheduler(string packageName, int priority) { if (_schedulerDic.ContainsKey(packageName)) { @@ -131,7 +132,7 @@ namespace YooAsset /// /// 销毁包裹调度器 /// - internal static void DestroyPackageScheduler(string packageName) + public static void DestroyPackageScheduler(string packageName) { // 不允许销毁默认调度器 if (packageName == GLOBAL_SCHEDULER_NAME) @@ -165,47 +166,11 @@ namespace YooAsset scheduler.StartOperation(operation); } - /// - /// 监听任务开始 - /// - public static void RegisterStartCallback(Action callback) - { - _startCallback = callback; - } - - /// - /// 监听任务结束 - /// - public static void RegisterFinishCallback(Action callback) - { - _finishCallback = callback; - } - - /// - /// 触发任务开始回调 - /// - internal static void InvokeStartCallback(string packageName, AsyncOperationBase operation) - { - _startCallback?.Invoke(packageName, operation); - } - - /// - /// 触发任务完成回调 - /// - internal static void InvokeFinishCallback(string packageName, AsyncOperationBase operation) - { - _finishCallback?.Invoke(packageName, operation); - } - /// /// 获取调度器(严格模式) /// private static OperationScheduler GetScheduler(string packageName) { - // 空包名路由到默认调度器 - if (string.IsNullOrEmpty(packageName)) - packageName = GLOBAL_SCHEDULER_NAME; - if (_schedulerDic.TryGetValue(packageName, out var scheduler)) { return scheduler; @@ -218,16 +183,8 @@ namespace YooAsset #region 调试信息 internal static List GetDebugOperationInfos(string packageName) { - // 空包名路由到默认调度器 - if (string.IsNullOrEmpty(packageName)) - packageName = GLOBAL_SCHEDULER_NAME; - - if (_schedulerDic.TryGetValue(packageName, out var scheduler)) - { - return scheduler.GetDebugOperationInfos(); - } - - return new List(); + var scheduler = GetScheduler(packageName); + return scheduler.GetDebugOperationInfos(); } #endregion } diff --git a/Assets/YooAsset/Runtime/OperationSystem/README.md b/Assets/YooAsset/Runtime/OperationSystem/README.md index 56ee82f5..14bffc49 100644 --- a/Assets/YooAsset/Runtime/OperationSystem/README.md +++ b/Assets/YooAsset/Runtime/OperationSystem/README.md @@ -56,8 +56,8 @@ OperationSystem 是 YooAsset 资源管理系统的**异步操作调度核心** ### 核心组件 - **OperationSystem**: 静态调度器,管理所有操作的执行 +- **OperationScheduler**: 包裹级调度器,维护操作队列并负责更新调度 - **AsyncOperationBase**: 异步操作基类,定义生命周期和状态 -- **GameAsyncOperation**: 游戏层操作基类,提供更友好的 API - **EOperationStatus**: 操作状态枚举 --- @@ -68,8 +68,8 @@ OperationSystem 是 YooAsset 资源管理系统的**异步操作调度核心** OperationSystem/ ├── EOperationStatus.cs # 操作状态枚举 ├── AsyncOperationBase.cs # 异步操作基类 +├── OperationScheduler.cs # 包裹级调度器 ├── OperationSystem.cs # 异步操作调度器 -└── GameAsyncOperation.cs # 游戏层操作基类 ``` --- @@ -113,12 +113,21 @@ None ─────────────────► Processing ─── | `Status` | `EOperationStatus` | 当前状态 | | `Error` | `string` | 错误信息(失败时) | | `Progress` | `float` | 处理进度(0-1) | -| `PackageName` | `string` | 所属包裹名称 | | `IsDone` | `bool` | 是否已完成(Succeed 或 Failed) | | `Task` | `Task` | 用于 async/await | | `BeginTime` | `string` | 开始时间(调试用) | | `ProcessTime` | `long` | 处理耗时毫秒(调试用) | +> 说明:`AsyncOperationBase` 本身不保存包裹名称;包裹名称由 `OperationSystem.StartOperation(packageName, operation)` 传入,并由 `OperationScheduler` 维护。 + +#### 内部协作:时间切片(`IsBusy`) + +为配合 `OperationSystem.MaxTimeSlice` 的时间切片预算,`AsyncOperationBase` 提供了内部属性 `IsBusy`(`internal`)用于任务在 `InternalUpdate()` 内主动让出本帧预算。 + +- 推荐用法:在 `InternalUpdate()` 内部(或内部子步骤)在执行重逻辑前判断 `IsBusy`,若繁忙则 `return`,把工作拆到下一帧继续执行。 +- 同步等待特殊处理:当调用了 `WaitForAsyncComplete()` 进入同步等待阶段时,`IsBusy` 会强制返回 `false`,避免因时间切片判断导致同步等待无法推进。 +- 注意:`WaitForAsyncComplete()` 会阻塞主线程,应谨慎使用;同步等待阶段不受时间切片保护,可能带来卡顿。 + #### 公共事件 ```csharp @@ -150,14 +159,16 @@ public void WaitForAsyncComplete(); #### 子任务管理 ```csharp -// 子任务列表 -internal readonly List Childs; - -// 添加/移除子任务 +// 添加/移除子任务(内部使用) internal void AddChildOperation(AsyncOperationBase child); internal void RemoveChildOperation(AsyncOperationBase child); ``` +**调用约束(重要):** +- 仅允许在 Unity 主线程调用(与 `OperationSystem.Update()` 的调度线程一致)。 +- 不要在 `InternalUpdate()` 正在遍历/处理中途频繁增删子任务;推荐在任务启动阶段完成子任务挂接,或在确保无并发修改风险的安全点调整。 +- `AbortOperation()` 会递归中止子任务,子任务的生命周期由父任务统一管理;避免在 `Completed` 回调里再去修改子任务关系,防止时序混乱。 + --- ### OperationSystem(调度器) @@ -208,6 +219,12 @@ public static void ClearPackageOperation(string packageName); public static void StartOperation(string packageName, AsyncOperationBase operation); ``` +#### 包裹调度说明 + +- `packageName` 不允许为空(`null` / `""`),否则会抛出异常。 +- 若需要使用全局调度器,请传入 `OperationSystem.GLOBAL_SCHEDULER_NAME`(`Initialize()` 时自动创建)。 +- `packageName` 为非全局调度器名称时,必须先通过 `YooAssets.CreatePackage(packageName)` 创建包裹(内部会注册对应 `OperationScheduler`),否则会抛出异常。 + #### 回调监听 ```csharp @@ -224,47 +241,6 @@ public static void RegisterFinishCallback(Action cal --- -### GameAsyncOperation(游戏层基类) - -继承 `AsyncOperationBase`,为业务层提供更友好的 API。 - -```csharp -public abstract class GameAsyncOperation : AsyncOperationBase -{ - /// - /// 异步操作开始 - /// - protected abstract void OnStart(); - - /// - /// 异步操作更新 - /// - protected abstract void OnUpdate(); - - /// - /// 异步操作终止 - /// - protected abstract void OnAbort(); - - /// - /// 异步等待完成(可选重写) - /// - protected virtual void OnWaitForAsyncComplete(); - - /// - /// 异步操作系统是否繁忙 - /// - protected bool IsBusy(); - - /// - /// 终止异步操作 - /// - protected void Abort(); -} -``` - ---- - ## 异步编程模式 ### 1. 协程模式(IEnumerator) @@ -345,9 +321,9 @@ operation.Priority = 100; // 设置高优先级 ``` **排序规则:** -- 新操作添加时检查是否需要排序 -- 仅当存在非零优先级时触发排序 -- 使用 `List.Sort()` 进行原地排序 +- 新操作添加时:若新增队列存在非零优先级,则触发排序 +- 运行时修改 `Priority`:会在下一次调度器更新时自动触发重排(即时生效,通常为下一帧) +- 排序使用 `List.Sort()` 进行原地排序;频繁修改优先级会带来额外排序开销,建议按需使用 ### 时间切片 @@ -358,6 +334,10 @@ operation.Priority = 100; // 设置高优先级 OperationSystem.MaxTimeSlice = 8; ``` +**操作侧协作建议:** +- 在操作的 `InternalUpdate()` 中使用 `IsBusy`(`AsyncOperationBase` 的内部属性)进行“自愿让出”,将重任务拆分到多帧执行。 +- 在同步等待(`WaitForAsyncComplete()`)阶段,`IsBusy` 会强制返回 `false`,以保证同步等待推进;此时需要自行评估卡顿风险。 + **执行流程:** ``` @@ -420,24 +400,29 @@ OperationSystem.MaxTimeSlice = 8; ### 调试信息结构 ```csharp +[Serializable] internal struct DebugOperationInfo { - public string OperationName; // 操作类型名 - public string OperationDesc; // 操作描述 + public string OperationName; // 任务名称 + public string OperationDesc; // 任务说明 public uint Priority; // 优先级 - public float Progress; // 进度 - public string BeginTime; // 开始时间 - public long ProcessTime; // 处理耗时(毫秒) - public string Status; // 状态 - public List Childs; // 子操作 + public float Progress; // 任务进度 + public string BeginTime; // 任务开始的时间 + public long ProcessTime; // 处理耗时(单位:毫秒) + public string Status; // 任务状态 + public List Childs; // 子任务列表(注意:JsonUtility 序列化深度限制) } ``` +> 说明:该结构体真实定义位于 `Runtime/DiagnosticSystem/DebugOperationInfo.cs`,这里仅展示关键字段以便理解。 + ### 获取调试信息 ```csharp -// 获取指定包裹的所有操作信息 -var infos = OperationSystem.GetDebugOperationInfos("DefaultPackage"); +// 获取指定包裹的所有操作信息(内部调试接口) +// packageName 不允许为空;全局调度器请使用 OperationSystem.GLOBAL_SCHEDULER_NAME +// 非全局包裹需先 YooAssets.CreatePackage(packageName) +var infos = OperationSystem.GetDebugOperationInfos(OperationSystem.GLOBAL_SCHEDULER_NAME); foreach (var info in infos) { @@ -457,105 +442,6 @@ Debug.Log($"处理耗时: {operation.ProcessTime}ms"); --- -## 使用示例 - -### 自定义异步操作 - -```csharp -public class MyCustomOperation : GameAsyncOperation -{ - private int _step = 0; - - protected override void OnStart() - { - // 初始化操作 - _step = 0; - } - - protected override void OnUpdate() - { - // 检查系统是否繁忙(时间切片) - if (IsBusy()) - return; - - // 执行步骤 - switch (_step) - { - case 0: - // 第一步 - Progress = 0.3f; - _step = 1; - break; - case 1: - // 第二步 - Progress = 0.6f; - _step = 2; - break; - case 2: - // 完成 - Status = EOperationStatus.Succeed; - break; - } - } - - protected override void OnAbort() - { - // 清理资源 - } -} -``` - -### 启动自定义操作 - -```csharp -var operation = new MyCustomOperation(); -OperationSystem.StartOperation("DefaultPackage", operation); - -// 使用回调 -operation.Completed += (op) => -{ - if (op.Status == EOperationStatus.Succeed) - Debug.Log("操作成功"); -}; - -// 或使用 await -await operation.Task; -``` - -### 带子任务的操作 - -```csharp -public class ParentOperation : GameAsyncOperation -{ - private ChildOperation _child; - - protected override void OnStart() - { - _child = new ChildOperation(); - AddChildOperation(_child); // 添加子任务 - OperationSystem.StartOperation(PackageName, _child); - } - - protected override void OnUpdate() - { - if (_child.IsDone) - { - if (_child.Status == EOperationStatus.Succeed) - Status = EOperationStatus.Succeed; - else - Status = EOperationStatus.Failed; - } - } - - protected override void OnAbort() - { - // 子任务会自动中止 - } -} -``` - ---- - ## 设计模式 ### 模板方法模式 @@ -589,7 +475,7 @@ AsyncOperationBase ### 组合模式 -通过 `Childs` 列表支持父子操作关系: +通过内部子任务列表支持父子操作关系: ``` ParentOperation @@ -608,10 +494,6 @@ IEnumerator + IComparable │ ▼ AsyncOperationBase (抽象基类) - │ - ├── GameAsyncOperation (游戏层基类) - │ │ - │ └── [业务层自定义操作] │ └── [YooAsset 内部操作] │ @@ -632,4 +514,4 @@ IEnumerator + IComparable 4. **子任务中止**:父操作中止时会自动中止所有子操作 5. **回调异常**:`Completed` 回调中的异常会被捕获并记录,不会中断系统 6. **编辑器重置**:编辑器中使用 `RuntimeInitializeOnLoadMethod` 自动重置状态 -7. **循环保护**:`WaitForAsyncComplete()` 有 1000 帧上限,防止无限循环 +7. **循环保护**:在 `InternalWaitForAsyncComplete()` 中如果使用 `ExecuteWhileDone()`,内部默认有 1000 次执行保护,防止无限循环 diff --git a/Assets/YooAsset/Runtime/ResourceManager/Operation/InstantiateOperation.cs b/Assets/YooAsset/Runtime/ResourceManager/Operation/InstantiateOperation.cs index ef4f32fc..8807c66f 100644 --- a/Assets/YooAsset/Runtime/ResourceManager/Operation/InstantiateOperation.cs +++ b/Assets/YooAsset/Runtime/ResourceManager/Operation/InstantiateOperation.cs @@ -62,6 +62,9 @@ namespace YooAsset return; } + if (IsWaitForAsyncComplete) + _handle.WaitForAsyncComplete(); + if (_handle.IsDone == false) return; @@ -138,18 +141,7 @@ namespace YooAsset } internal override void InternalWaitForAsyncComplete() { - while (true) - { - // 等待句柄完成 - if (_handle != null) - _handle.WaitForAsyncComplete(); - - if (ExecuteWhileDone()) - { - _steps = ESteps.Done; - break; - } - } + RunBatchExecution(); } internal override string InternalGetDesc() { diff --git a/Assets/YooAsset/Runtime/ResourceManager/Operation/Internal/LoadBundleFileOperation.cs b/Assets/YooAsset/Runtime/ResourceManager/Operation/Internal/LoadBundleFileOperation.cs index 4db2dd11..cb032bb7 100644 --- a/Assets/YooAsset/Runtime/ResourceManager/Operation/Internal/LoadBundleFileOperation.cs +++ b/Assets/YooAsset/Runtime/ResourceManager/Operation/Internal/LoadBundleFileOperation.cs @@ -127,14 +127,7 @@ namespace YooAsset } internal override void InternalWaitForAsyncComplete() { - while (true) - { - if (ExecuteWhileDone()) - { - _steps = ESteps.Done; - break; - } - } + RunBatchExecution(); } internal override string InternalGetDesc() { diff --git a/Assets/YooAsset/Runtime/ResourceManager/Operation/UnloadUnusedAssetsOperation.cs b/Assets/YooAsset/Runtime/ResourceManager/Operation/UnloadUnusedAssetsOperation.cs index 9aa01a4a..5ab47cbd 100644 --- a/Assets/YooAsset/Runtime/ResourceManager/Operation/UnloadUnusedAssetsOperation.cs +++ b/Assets/YooAsset/Runtime/ResourceManager/Operation/UnloadUnusedAssetsOperation.cs @@ -53,14 +53,7 @@ namespace YooAsset } internal override void InternalWaitForAsyncComplete() { - while (true) - { - if (ExecuteWhileDone()) - { - _steps = ESteps.Done; - break; - } - } + RunBatchExecution(); } internal override string InternalGetDesc() { diff --git a/Assets/YooAsset/Runtime/ResourceManager/Provider/ProviderOperation.cs b/Assets/YooAsset/Runtime/ResourceManager/Provider/ProviderOperation.cs index 719ea425..74e2447e 100644 --- a/Assets/YooAsset/Runtime/ResourceManager/Provider/ProviderOperation.cs +++ b/Assets/YooAsset/Runtime/ResourceManager/Provider/ProviderOperation.cs @@ -183,14 +183,7 @@ namespace YooAsset } internal override void InternalWaitForAsyncComplete() { - while (true) - { - if (ExecuteWhileDone()) - { - _steps = ESteps.Done; - break; - } - } + RunBatchExecution(); } internal override string InternalGetDesc() { diff --git a/Assets/YooAsset/Runtime/ResourcePackage/EBuildBundleType.cs b/Assets/YooAsset/Runtime/ResourcePackage/EBuildBundleType.cs index 99b658fe..5ec8b48e 100644 --- a/Assets/YooAsset/Runtime/ResourcePackage/EBuildBundleType.cs +++ b/Assets/YooAsset/Runtime/ResourcePackage/EBuildBundleType.cs @@ -22,5 +22,10 @@ namespace YooAsset /// 原生文件 /// RawBundle = 3, + + /// + /// 团结资源包 + /// + InstantBundle = 4, } } \ No newline at end of file diff --git a/Assets/YooAsset/Runtime/ResourcePackage/Operation/Internal/DeserializeManifestOperation.cs b/Assets/YooAsset/Runtime/ResourcePackage/Operation/Internal/DeserializeManifestOperation.cs index d354e63c..87afcfcc 100644 --- a/Assets/YooAsset/Runtime/ResourcePackage/Operation/Internal/DeserializeManifestOperation.cs +++ b/Assets/YooAsset/Runtime/ResourcePackage/Operation/Internal/DeserializeManifestOperation.cs @@ -220,14 +220,7 @@ namespace YooAsset } internal override void InternalWaitForAsyncComplete() { - while (true) - { - if (ExecuteWhileDone()) - { - _steps = ESteps.Done; - break; - } - } + RunBatchExecution(); } private void CreateAssetCollection(PackageManifest manifest, int assetCount) diff --git a/Assets/YooAsset/Runtime/ResourcePackage/ResourcePackage.cs b/Assets/YooAsset/Runtime/ResourcePackage/ResourcePackage.cs index c1343355..bb07e1f5 100644 --- a/Assets/YooAsset/Runtime/ResourcePackage/ResourcePackage.cs +++ b/Assets/YooAsset/Runtime/ResourcePackage/ResourcePackage.cs @@ -213,7 +213,7 @@ namespace YooAsset options.ReleaseAllHandles = true; options.LockLoadOperation = true; var operation = new DestroyOperation(this, options); - OperationSystem.StartOperation(null, operation); + OperationSystem.StartOperation(OperationSystem.GLOBAL_SCHEDULER_NAME, operation); return operation; } diff --git a/Assets/YooAsset/Runtime/YooAssets.cs b/Assets/YooAsset/Runtime/YooAssets.cs index 635b1822..813e2b3d 100644 --- a/Assets/YooAsset/Runtime/YooAssets.cs +++ b/Assets/YooAsset/Runtime/YooAssets.cs @@ -225,7 +225,7 @@ namespace YooAsset public static void StartOperation(GameAsyncOperation operation) { // 注意:游戏业务逻辑的包裹填写为空 - OperationSystem.StartOperation(string.Empty, operation); + OperationSystem.StartOperation(OperationSystem.GLOBAL_SCHEDULER_NAME, operation); }