diff --git a/.gitignore b/.gitignore index c7f49e6..1a55ae5 100644 --- a/.gitignore +++ b/.gitignore @@ -4,4 +4,5 @@ obj/ riderModule.iml /_ReSharper.Caches/ GFramework.sln.DotSettings.user -.idea/ \ No newline at end of file +.idea/ +opencode.json \ No newline at end of file diff --git a/GFramework.Core/coroutine/CoroutineHandle.cs b/GFramework.Core/coroutine/CoroutineHandle.cs index a7ebd3e..eec12d2 100644 --- a/GFramework.Core/coroutine/CoroutineHandle.cs +++ b/GFramework.Core/coroutine/CoroutineHandle.cs @@ -111,33 +111,85 @@ public class CoroutineHandle : IYieldInstruction, ICoroutineHandle { if (IsDone) return false; - // 检查并更新当前等待的指令 + // 如果有等待指令,先更新等待指令 if (_waitingInstruction != null) { _waitingInstruction.Update(deltaTime); - if (!_waitingInstruction.IsDone) return true; + + // 如果等待指令还未完成,继续等待 + if (!_waitingInstruction.IsDone) + { + return true; + } + + // 等待指令已完成,清除它 _waitingInstruction = null; } - // 循环执行直到需要等待或协程完成 - while (_stack.Count > 0 && !IsDone) + // 每帧只推进一步(执行一个 MoveNext) + if (_stack.Count > 0) { try { var current = _stack.Peek(); - if (current.MoveNext()) + bool hasNext = current.MoveNext(); + + if (!hasNext) { - var yielded = current.Current; - var needsWait = ProcessYieldValue(yielded); + // 当前枚举器已完成,弹出栈 + _stack.Pop(); + + // 如果栈为空,协程完成 + if (_stack.Count == 0) + { + Complete(); + return false; + } + + // 否则继续执行下一个枚举器(在下一帧) + return true; + } + + // MoveNext() 返回 true,有下一个值 + var yielded = current.Current; + var needsWait = ProcessYieldValue(yielded); - // 如果需要等待,则暂停执行 - if (needsWait) return true; - - // 否则继续执行下一个步骤 - continue; + // 如果需要等待,则暂停执行 + if (needsWait) + { + return true; } - _stack.Pop(); + // 如果不需要等待(yield null 或嵌套协程),继续处理 + // 处理 yield null 的情况:yield null 后需要再调用一次 MoveNext 才能知道是否完成 + if (yielded == null) + { + // yield null 意味着等待一帧,但协程可能还没有完成 + // 需要再次检查是否还有更多步骤 + bool stillHasNext = current.MoveNext(); + if (!stillHasNext) + { + // 协程确实完成了 + _stack.Pop(); + if (_stack.Count == 0) + { + Complete(); + return false; + } + } + else + { + // 还有更多内容,yield 出来的值需要处理 + yielded = current.Current; + needsWait = ProcessYieldValue(yielded); + if (needsWait) + { + return true; + } + } + } + + return true; } catch (Exception ex) { @@ -146,13 +198,9 @@ public class CoroutineHandle : IYieldInstruction, ICoroutineHandle } } - if (_stack.Count == 0) - { - Complete(); - return false; - } - - return true; + // 栈为空,协程完成 + Complete(); + return false; } /// @@ -165,25 +213,31 @@ public class CoroutineHandle : IYieldInstruction, ICoroutineHandle switch (yielded) { case CoroutineHandle otherHandle: - // 标记子协程由父协程管理 - if (!otherHandle.IsDone) + // 处理 yield return CoroutineHandle + if (otherHandle.IsDone) { - otherHandle.MarkAsManagedByParent(); - _waitingInstruction = otherHandle; - return true; // 需要等待子协程完成 + // 子协程已完成,不需要等待 + return false; } - return false; // 子协程已完成,不需要等待 + + // 标记子协程由父协程管理 + otherHandle.MarkAsManagedByParent(); + _waitingInstruction = otherHandle; + return true; // 需要等待子协程完成 case IEnumerator nested: + // 处理 yield return IEnumerator(嵌套协程) _stack.Push(nested); - return false; // 压入嵌套协程,立即执行 + return false; // 压入嵌套协程,在下一帧继续执行 case IYieldInstruction instruction: + // 处理 yield return IYieldInstruction _waitingInstruction = instruction; return true; // 需要等待指令完成 case null: - return false; // null,立即继续 + // 处理 yield return null(等待一帧) + return false; // null 立即继续,但会返回 true 让协程继续执行 default: throw new InvalidOperationException($"Unsupported yield type: {yielded.GetType()}"); diff --git a/GFramework.Core/coroutine/CoroutineScheduler.cs b/GFramework.Core/coroutine/CoroutineScheduler.cs index d53c6ca..f33860d 100644 --- a/GFramework.Core/coroutine/CoroutineScheduler.cs +++ b/GFramework.Core/coroutine/CoroutineScheduler.cs @@ -25,16 +25,19 @@ public class CoroutineScheduler : ICoroutineScheduler $"Owner: {_ownerThreadId}, Current: {Thread.CurrentThread.ManagedThreadId}"); } + // 先将新协程添加到活动列表 if (_toAdd.Count > 0) { _active.AddRange(_toAdd); _toAdd.Clear(); } + // 遍历活动协程,每帧只推进一步 for (var i = _active.Count - 1; i >= 0; i--) { var c = _active[i]; + // 检查作用域是否仍然活跃 if (!c.Context.Scope.IsActive) { c.Cancel(); @@ -46,21 +49,29 @@ public class CoroutineScheduler : ICoroutineScheduler if (c.IsManagedByParent) continue; + // 更新协程,每帧只推进一步 ((IYieldInstruction)c).Update(deltaTime); + + // 如果协程完成,标记为待移除 if (c.IsDone) _toRemove.Add(c); } - if (_toRemove.Count <= 0) return; - - _active.RemoveAll(c => _toRemove.Contains(c)); - _toRemove.Clear(); + // 移除已完成的协程 + if (_toRemove.Count > 0) + { + _active.RemoveAll(c => _toRemove.Contains(c)); + _toRemove.Clear(); + } } internal CoroutineHandle StartCoroutine(IEnumerator routine, CoroutineContext context) { var handle = new CoroutineHandle(routine, context, null); + + // 添加到调度队列,协程将在下次 Update 时开始执行 _toAdd.Add(handle); + return handle; } diff --git a/GFramework.Core/coroutine/CoroutineScopeExtensions.cs b/GFramework.Core/coroutine/CoroutineScopeExtensions.cs index c989de2..7c5293d 100644 --- a/GFramework.Core/coroutine/CoroutineScopeExtensions.cs +++ b/GFramework.Core/coroutine/CoroutineScopeExtensions.cs @@ -30,6 +30,7 @@ public static class CoroutineScopeExtensions { yield return new WaitForSeconds(delay); action?.Invoke(); + yield break; // 确保协程正确结束 } /// @@ -52,11 +53,11 @@ public static class CoroutineScopeExtensions /// 协程迭代器 private static IEnumerator RepeatingRoutine(float interval, Action action) { - // 持续循环执行动作并等待指定间隔 + // 持续循环等待指定间隔后执行动作 while (true) { - action?.Invoke(); yield return new WaitForSeconds(interval); + action?.Invoke(); // 先等待,再执行 } } } \ No newline at end of file diff --git a/GFramework.Core/coroutine/WaitUntil.cs b/GFramework.Core/coroutine/WaitUntil.cs index f973ee8..08151a8 100644 --- a/GFramework.Core/coroutine/WaitUntil.cs +++ b/GFramework.Core/coroutine/WaitUntil.cs @@ -19,7 +19,7 @@ public class WaitUntil(Func predicate) : IYieldInstruction /// 时间增量 public void Update(float deltaTime) { - // 只有在未完成状态下才检查条件 + // 每次更新都重新评估条件,但一旦完成就保持完成状态 if (!IsDone) IsDone = predicate(); }