From 7198e639d949c8df882ae1a127a4c08055b2004d 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 16:10:24 +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 --- .../OperationSystem/AsyncOperationBase.cs | 54 +++++++++++++++++-- .../OperationSystem/OperationSystem.cs | 4 +- Assets/YooAsset/Runtime/YooAssets.cs | 17 ++---- Assets/YooAsset/Runtime/YooAssetsDriver.cs | 2 +- 4 files changed, 57 insertions(+), 20 deletions(-) diff --git a/Assets/YooAsset/Runtime/OperationSystem/AsyncOperationBase.cs b/Assets/YooAsset/Runtime/OperationSystem/AsyncOperationBase.cs index f48121df..64d59e86 100644 --- a/Assets/YooAsset/Runtime/OperationSystem/AsyncOperationBase.cs +++ b/Assets/YooAsset/Runtime/OperationSystem/AsyncOperationBase.cs @@ -155,9 +155,19 @@ namespace YooAsset if (_childs == null) _childs = new List(10); -#if UNITY_EDITOR +#if UNITY_EDITOR || DEBUG + if (child == null) + throw new YooInternalException("The child node is null !"); + + if (ReferenceEquals(child, this)) + throw new YooInternalException("The child node cannot be itself !"); + if (_childs.Contains(child)) throw new YooInternalException($"The child node {child.GetType().Name} already exists !"); + + // 禁止形成环依赖 + if (WouldCreateCycle(child)) + throw new YooInternalException($"AddChildOperation would create a cycle : {this.GetType().Name} -> {child.GetType().Name}"); #endif _childs.Add(child); @@ -171,7 +181,10 @@ namespace YooAsset if (_childs == null) return; -#if UNITY_EDITOR +#if UNITY_EDITOR || DEBUG + if (child == null) + throw new YooInternalException("The child node is null !"); + if (_childs.Contains(child) == false) throw new YooInternalException($"The child node {child.GetType().Name} not exists !"); #endif @@ -349,10 +362,10 @@ namespace YooAsset if (IsWaitForAsyncComplete == false) { IsWaitForAsyncComplete = true; - + if (IsDone == false) InternalWaitForAsyncComplete(); - + if (IsDone == false) { Status = EOperationStatus.Failed; @@ -415,6 +428,39 @@ namespace YooAsset float s = UnityEngine.Mathf.FloorToInt(spawnTime - m * 60f - h * 3600f); return h.ToString("00") + ":" + m.ToString("00") + ":" + s.ToString("00"); } + private bool WouldCreateCycle(AsyncOperationBase child) + { + const int maxVisited = 4096; + var stack = new Stack(); + var visited = new HashSet(); + stack.Push(child); + + while (stack.Count > 0) + { + var node = stack.Pop(); + if (node == null) + continue; + + if (visited.Add(node) == false) + continue; + + if (visited.Count > maxVisited) + throw new YooInternalException("Child operation graph is too large, cycle check aborted !"); + + if (ReferenceEquals(node, this)) + return true; + + if (node._childs == null) + continue; + + for (int i = 0; i < node._childs.Count; i++) + { + stack.Push(node._childs[i]); + } + } + + return false; + } internal DebugOperationInfo GetDebugOperationInfo() { diff --git a/Assets/YooAsset/Runtime/OperationSystem/OperationSystem.cs b/Assets/YooAsset/Runtime/OperationSystem/OperationSystem.cs index b507cea5..876c4aba 100644 --- a/Assets/YooAsset/Runtime/OperationSystem/OperationSystem.cs +++ b/Assets/YooAsset/Runtime/OperationSystem/OperationSystem.cs @@ -97,6 +97,8 @@ namespace YooAsset /// public static void DestroyAll() { + YooLogger.Log("Operation system destroy all !"); + // 清空所有调度器 foreach (var scheduler in _schedulerList) { @@ -177,7 +179,7 @@ namespace YooAsset } // 严格模式:非默认包裹必须先创建调度器 - throw new YooInternalException($"Package scheduler not found: {packageName}. Please call YooAssets.CreatePackage() first!"); + throw new YooInternalException($"Operation scheduler not found: {packageName}. Please call YooAssets.CreatePackage() first!"); } #region 调试信息 diff --git a/Assets/YooAsset/Runtime/YooAssets.cs b/Assets/YooAsset/Runtime/YooAssets.cs index 813e2b3d..1e199266 100644 --- a/Assets/YooAsset/Runtime/YooAssets.cs +++ b/Assets/YooAsset/Runtime/YooAssets.cs @@ -59,6 +59,7 @@ namespace YooAsset _driver.AddComponent(); #endif + // 初始化异步操作系统 OperationSystem.Initialize(); } } @@ -75,8 +76,8 @@ namespace YooAsset if (_driver != null) GameObject.Destroy(_driver); - // 终止并清空所有包裹的异步操作 - ClearAllPackageOperation(); + // 销毁异步操作系统 + OperationSystem.DestroyAll(); // 卸载所有AssetBundle AssetBundle.UnloadAllAssetBundles(true); @@ -97,18 +98,6 @@ namespace YooAsset } } - /// - /// 终止并清空所有包裹的异步操作 - /// - internal static void ClearAllPackageOperation() - { - foreach (var package in _packages) - { - OperationSystem.ClearPackageOperation(package.PackageName); - } - OperationSystem.DestroyAll(); - } - /// /// 创建资源包裹 /// diff --git a/Assets/YooAsset/Runtime/YooAssetsDriver.cs b/Assets/YooAsset/Runtime/YooAssetsDriver.cs index 4adb4e40..b42a1238 100644 --- a/Assets/YooAsset/Runtime/YooAssetsDriver.cs +++ b/Assets/YooAsset/Runtime/YooAssetsDriver.cs @@ -25,7 +25,7 @@ namespace YooAsset void OnApplicationQuit() { // 说明:在编辑器下确保播放被停止时IO类操作被终止。 - YooAssets.ClearAllPackageOperation(); + YooAssets.Destroy(); } #endif