mirror of
https://github.com/GeWuYou/GFramework.git
synced 2026-03-22 10:34:30 +08:00
- 添加协程上下文、句柄、调度器和作用域管理类 - 实现协程等待指令包括 WaitForSeconds、WaitUntil 和 WaitWhile - 创建协程系统和全局协程作用域管理器 - 定义协程相关抽象接口 ICoroutineScheduler、ICoroutineScope 等 - 升级 Meziantou.Analyzer 依赖版本至 2.0.283 - 升级 Meziantou.Polyfill 依赖版本至 1.0.100
118 lines
2.9 KiB
C#
118 lines
2.9 KiB
C#
using System.Collections;
|
|
using GFramework.Game.Abstractions.coroutine;
|
|
|
|
namespace GFramework.Game.coroutine;
|
|
|
|
public class CoroutineHandle : IYieldInstruction
|
|
{
|
|
private readonly Stack<IEnumerator> _stack = new();
|
|
private IYieldInstruction? _waitingInstruction;
|
|
|
|
internal CoroutineHandle(IEnumerator routine, CoroutineContext context, IYieldInstruction? waitingInstruction)
|
|
{
|
|
_stack.Push(routine);
|
|
Context = context;
|
|
_waitingInstruction = waitingInstruction;
|
|
}
|
|
|
|
public CoroutineContext Context { get; }
|
|
public bool IsCancelled { get; private set; }
|
|
public bool IsDone { get; private set; }
|
|
|
|
void IYieldInstruction.Update(float deltaTime)
|
|
{
|
|
InternalUpdate(deltaTime);
|
|
}
|
|
|
|
public event Action? OnComplete;
|
|
public event Action<Exception>? OnError;
|
|
|
|
private bool InternalUpdate(float deltaTime)
|
|
{
|
|
if (IsDone) return false;
|
|
|
|
if (_waitingInstruction != null)
|
|
{
|
|
_waitingInstruction.Update(deltaTime);
|
|
if (!_waitingInstruction.IsDone) return true;
|
|
_waitingInstruction = null;
|
|
}
|
|
|
|
if (_stack.Count == 0)
|
|
{
|
|
Complete();
|
|
return false;
|
|
}
|
|
|
|
try
|
|
{
|
|
var current = _stack.Peek();
|
|
if (current.MoveNext())
|
|
{
|
|
ProcessYieldValue(current.Current);
|
|
return true;
|
|
}
|
|
|
|
_stack.Pop();
|
|
return _stack.Count > 0 || !CompleteCheck();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
HandleError(ex);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
private void ProcessYieldValue(object yielded)
|
|
{
|
|
switch (yielded)
|
|
{
|
|
case null:
|
|
break;
|
|
case IEnumerator nested:
|
|
_stack.Push(nested);
|
|
break;
|
|
// ✅ 将更具体的类型放在前面
|
|
case CoroutineHandle otherHandle:
|
|
_waitingInstruction = otherHandle;
|
|
break;
|
|
case IYieldInstruction instruction:
|
|
_waitingInstruction = instruction;
|
|
break;
|
|
default:
|
|
throw new InvalidOperationException($"Unsupported yield type: {yielded.GetType()}");
|
|
}
|
|
}
|
|
|
|
private bool CompleteCheck()
|
|
{
|
|
if (_stack.Count == 0) Complete();
|
|
return IsDone;
|
|
}
|
|
|
|
private void Complete()
|
|
{
|
|
if (IsDone) return;
|
|
IsDone = true;
|
|
_stack.Clear();
|
|
_waitingInstruction = null;
|
|
OnComplete?.Invoke();
|
|
}
|
|
|
|
private void HandleError(Exception ex)
|
|
{
|
|
IsDone = true;
|
|
_stack.Clear();
|
|
_waitingInstruction = null;
|
|
OnError?.Invoke(ex);
|
|
}
|
|
|
|
public void Cancel()
|
|
{
|
|
if (IsDone) return;
|
|
IsDone = true;
|
|
IsCancelled = true;
|
|
_stack.Clear();
|
|
_waitingInstruction = null;
|
|
}
|
|
} |