docs(Timing): 添加完整注释文档并优化协程管理器实现

- 为 Timing 类添加了完整的 XML 文档注释,包括类说明、属性和方法描述
- 将协程调度器字段改为可空引用类型,提升类型安全性
- 添加了安全访问调度器的属性,避免未初始化时的潜在问题
- 优化了协程执行段切换逻辑,使用安全访问属性替代直接字段访问
- 完善了生命周期管理方法的文档注释
- 添加了协程控制 API 的详细注释,包括暂停、恢复、终止等功能
- 优化了延迟调用相关方法的实现和文档
- 改进了节点有效性检查方法的可读性
This commit is contained in:
GeWuYou 2026-01-21 20:45:00 +08:00
parent ddbf7af572
commit 9194ef9445

View File

@ -5,24 +5,53 @@ using Godot;
namespace GFramework.Godot.coroutine; namespace GFramework.Godot.coroutine;
/// <summary>
/// Godot协程管理器提供基于不同更新循环的协程调度功能
/// 支持Process、PhysicsProcess和DeferredProcess三种执行段的协程管理
/// </summary>
public partial class Timing : Node public partial class Timing : Node
{ {
private static Timing? _instance; private static Timing? _instance;
private static readonly Timing?[] ActiveInstances = new Timing?[16]; private static readonly Timing?[] ActiveInstances = new Timing?[16];
private CoroutineScheduler _deferredScheduler; private CoroutineScheduler? _deferredScheduler;
private GodotTimeSource? _deferredTimeSource; private GodotTimeSource? _deferredTimeSource;
private ushort _frameCounter; private ushort _frameCounter;
private byte _instanceId = 1; private byte _instanceId = 1;
private CoroutineScheduler _physicsScheduler; private CoroutineScheduler? _physicsScheduler;
private GodotTimeSource? _physicsTimeSource; private GodotTimeSource? _physicsTimeSource;
private CoroutineScheduler _processScheduler; private CoroutineScheduler? _processScheduler;
private GodotTimeSource? _processTimeSource; private GodotTimeSource? _processTimeSource;
/// <summary>
/// 获取Process调度器如果未初始化则抛出异常
/// </summary>
private CoroutineScheduler ProcessScheduler =>
_processScheduler ?? throw new InvalidOperationException(
"Timing not yet initialized (_Ready not executed)");
/// <summary>
/// 获取Physics调度器如果未初始化则抛出异常
/// </summary>
private CoroutineScheduler PhysicsScheduler =>
_physicsScheduler ?? throw new InvalidOperationException(
"Timing not yet initialized (_Ready not executed)");
/// <summary>
/// 获取Deferred调度器如果未初始化则抛出异常
/// </summary>
private CoroutineScheduler DeferredScheduler =>
_deferredScheduler ?? throw new InvalidOperationException(
"Timing not yet initialized (_Ready not executed)");
#region #region
/// <summary>
/// 获取Timing单例实例
/// 如果实例不存在则自动创建并添加到场景树根节点
/// </summary>
public static Timing Instance public static Timing Instance
{ {
get get
@ -50,16 +79,29 @@ public partial class Timing : Node
#region Debug #region Debug
/// <summary>
/// 获取Process段活跃协程数量
/// </summary>
public int ProcessCoroutines => _processScheduler?.ActiveCoroutineCount ?? 0; public int ProcessCoroutines => _processScheduler?.ActiveCoroutineCount ?? 0;
/// <summary>
/// 获取Physics段活跃协程数量
/// </summary>
public int PhysicsCoroutines => _physicsScheduler?.ActiveCoroutineCount ?? 0; public int PhysicsCoroutines => _physicsScheduler?.ActiveCoroutineCount ?? 0;
/// <summary>
/// 获取Deferred段活跃协程数量
/// </summary>
public int DeferredCoroutines => _deferredScheduler?.ActiveCoroutineCount ?? 0; public int DeferredCoroutines => _deferredScheduler?.ActiveCoroutineCount ?? 0;
#endregion #endregion
#region #region
/// <summary>
/// 节点就绪时的初始化方法
/// 设置处理优先级,初始化调度器,并注册实例
/// </summary>
public override void _Ready() public override void _Ready()
{ {
ProcessPriority = -1; ProcessPriority = -1;
@ -70,6 +112,10 @@ public partial class Timing : Node
RegisterInstance(); RegisterInstance();
} }
/// <summary>
/// 节点退出场景树时的清理方法
/// 从活动实例数组中移除当前实例并清理必要资源
/// </summary>
public override void _ExitTree() public override void _ExitTree()
{ {
if (_instanceId < ActiveInstances.Length) if (_instanceId < ActiveInstances.Length)
@ -78,11 +124,19 @@ public partial class Timing : Node
CleanupInstanceIfNecessary(); CleanupInstanceIfNecessary();
} }
/// <summary>
/// 清理实例引用
/// </summary>
private static void CleanupInstanceIfNecessary() private static void CleanupInstanceIfNecessary()
{ {
_instance = null; _instance = null;
} }
/// <summary>
/// 每帧处理逻辑
/// 更新Process调度器增加帧计数器并安排延迟处理
/// </summary>
/// <param name="delta">时间增量</param>
public override void _Process(double delta) public override void _Process(double delta)
{ {
_processScheduler?.Update(); _processScheduler?.Update();
@ -91,11 +145,20 @@ public partial class Timing : Node
CallDeferred(nameof(ProcessDeferred)); CallDeferred(nameof(ProcessDeferred));
} }
/// <summary>
/// 物理处理逻辑
/// 更新Physics调度器
/// </summary>
/// <param name="delta">物理时间增量</param>
public override void _PhysicsProcess(double delta) public override void _PhysicsProcess(double delta)
{ {
_physicsScheduler?.Update(); _physicsScheduler?.Update();
} }
/// <summary>
/// 延迟处理逻辑
/// 更新Deferred调度器
/// </summary>
private void ProcessDeferred() private void ProcessDeferred()
{ {
_deferredScheduler?.Update(); _deferredScheduler?.Update();
@ -105,6 +168,10 @@ public partial class Timing : Node
#region #region
/// <summary>
/// 初始化所有调度器和时间源
/// 创建Process、Physics和Deferred三个调度器实例
/// </summary>
private void InitializeSchedulers() private void InitializeSchedulers()
{ {
_processTimeSource = new GodotTimeSource(GetProcessDeltaTime); _processTimeSource = new GodotTimeSource(GetProcessDeltaTime);
@ -130,6 +197,10 @@ public partial class Timing : Node
); );
} }
/// <summary>
/// 注册当前实例到活动实例数组中
/// 如果当前ID已被占用则寻找可用ID
/// </summary>
private void RegisterInstance() private void RegisterInstance()
{ {
if (ActiveInstances[_instanceId] == null) if (ActiveInstances[_instanceId] == null)
@ -151,6 +222,11 @@ public partial class Timing : Node
throw new OverflowException("最多只能存在 15 个 Timing 实例"); throw new OverflowException("最多只能存在 15 个 Timing 实例");
} }
/// <summary>
/// 尝试设置物理处理优先级
/// 使用反射方式设置ProcessPhysicsPriority属性
/// </summary>
/// <param name="priority">物理处理优先级</param>
private static void TrySetPhysicsPriority(int priority) private static void TrySetPhysicsPriority(int priority)
{ {
try try
@ -172,6 +248,13 @@ public partial class Timing : Node
#region API #region API
/// <summary>
/// 在指定段运行协程
/// </summary>
/// <param name="coroutine">要运行的协程枚举器</param>
/// <param name="segment">协程执行段Process/PhysicsProcess/DeferredProcess</param>
/// <param name="tag">协程标签,用于批量操作</param>
/// <returns>协程句柄</returns>
public static CoroutineHandle RunCoroutine( public static CoroutineHandle RunCoroutine(
IEnumerator<IYieldInstruction> coroutine, IEnumerator<IYieldInstruction> coroutine,
Segment segment = Segment.Process, Segment segment = Segment.Process,
@ -180,6 +263,14 @@ public partial class Timing : Node
return Instance.RunCoroutineOnInstance(coroutine, segment, tag); return Instance.RunCoroutineOnInstance(coroutine, segment, tag);
} }
/// <summary>
/// 在当前实例上运行协程
/// 根据指定的段选择对应的调度器运行协程
/// </summary>
/// <param name="coroutine">要运行的协程枚举器</param>
/// <param name="segment">协程执行段</param>
/// <param name="tag">协程标签</param>
/// <returns>协程句柄</returns>
public CoroutineHandle RunCoroutineOnInstance( public CoroutineHandle RunCoroutineOnInstance(
IEnumerator<IYieldInstruction>? coroutine, IEnumerator<IYieldInstruction>? coroutine,
Segment segment = Segment.Process, Segment segment = Segment.Process,
@ -190,9 +281,9 @@ public partial class Timing : Node
return segment switch return segment switch
{ {
Segment.Process => _processScheduler.Run(coroutine, tag), Segment.Process => ProcessScheduler.Run(coroutine, tag),
Segment.PhysicsProcess => _physicsScheduler.Run(coroutine, tag), Segment.PhysicsProcess => PhysicsScheduler.Run(coroutine, tag),
Segment.DeferredProcess => _deferredScheduler.Run(coroutine, tag), Segment.DeferredProcess => DeferredScheduler.Run(coroutine, tag),
_ => default _ => default
}; };
} }
@ -201,67 +292,120 @@ public partial class Timing : Node
#region API #region API
/// <summary>
/// 暂停指定的协程
/// </summary>
/// <param name="handle">协程句柄</param>
/// <returns>是否成功暂停</returns>
public static bool PauseCoroutine(CoroutineHandle handle) public static bool PauseCoroutine(CoroutineHandle handle)
{ {
return GetInstance(handle.Key)?.PauseOnInstance(handle) ?? false; return GetInstance(handle.Key)?.PauseOnInstance(handle) ?? false;
} }
/// <summary>
/// 恢复指定的协程
/// </summary>
/// <param name="handle">协程句柄</param>
/// <returns>是否成功恢复</returns>
public static bool ResumeCoroutine(CoroutineHandle handle) public static bool ResumeCoroutine(CoroutineHandle handle)
{ {
return GetInstance(handle.Key)?.ResumeOnInstance(handle) ?? false; return GetInstance(handle.Key)?.ResumeOnInstance(handle) ?? false;
} }
/// <summary>
/// 终止指定的协程
/// </summary>
/// <param name="handle">协程句柄</param>
/// <returns>是否成功终止</returns>
public static bool KillCoroutine(CoroutineHandle handle) public static bool KillCoroutine(CoroutineHandle handle)
{ {
return GetInstance(handle.Key)?.KillOnInstance(handle) ?? false; return GetInstance(handle.Key)?.KillOnInstance(handle) ?? false;
} }
/// <summary>
/// 终止所有具有指定标签的协程
/// </summary>
/// <param name="tag">协程标签</param>
/// <returns>被终止的协程数量</returns>
public static int KillCoroutines(string tag) public static int KillCoroutines(string tag)
{ {
return Instance.KillByTagOnInstance(tag); return Instance.KillByTagOnInstance(tag);
} }
/// <summary>
/// 终止所有协程
/// </summary>
/// <returns>被终止的协程总数</returns>
public static int KillAllCoroutines() public static int KillAllCoroutines()
{ {
return Instance.ClearOnInstance(); return Instance.ClearOnInstance();
} }
/// <summary>
/// 在当前实例上暂停协程
/// 尝试在所有调度器中查找并暂停指定协程
/// </summary>
/// <param name="handle">协程句柄</param>
/// <returns>是否成功暂停</returns>
private bool PauseOnInstance(CoroutineHandle handle) private bool PauseOnInstance(CoroutineHandle handle)
{ {
return _processScheduler.Pause(handle) return ProcessScheduler.Pause(handle)
|| _physicsScheduler.Pause(handle) || PhysicsScheduler.Pause(handle)
|| _deferredScheduler.Pause(handle); || DeferredScheduler.Pause(handle);
} }
/// <summary>
/// 在当前实例上恢复协程
/// 尝试在所有调度器中查找并恢复指定协程
/// </summary>
/// <param name="handle">协程句柄</param>
/// <returns>是否成功恢复</returns>
private bool ResumeOnInstance(CoroutineHandle handle) private bool ResumeOnInstance(CoroutineHandle handle)
{ {
return _processScheduler.Resume(handle) return ProcessScheduler.Resume(handle)
|| _physicsScheduler.Resume(handle) || PhysicsScheduler.Resume(handle)
|| _deferredScheduler.Resume(handle); || DeferredScheduler.Resume(handle);
} }
/// <summary>
/// 在当前实例上终止协程
/// 尝试在所有调度器中查找并终止指定协程
/// </summary>
/// <param name="handle">协程句柄</param>
/// <returns>是否成功终止</returns>
private bool KillOnInstance(CoroutineHandle handle) private bool KillOnInstance(CoroutineHandle handle)
{ {
return _processScheduler.Kill(handle) return ProcessScheduler.Kill(handle)
|| _physicsScheduler.Kill(handle) || PhysicsScheduler.Kill(handle)
|| _deferredScheduler.Kill(handle); || DeferredScheduler.Kill(handle);
} }
/// <summary>
/// 在当前实例上根据标签终止协程
/// 在所有调度器中查找并终止具有指定标签的协程
/// </summary>
/// <param name="tag">协程标签</param>
/// <returns>被终止的协程数量</returns>
private int KillByTagOnInstance(string tag) private int KillByTagOnInstance(string tag)
{ {
int count = 0; int count = 0;
count += _processScheduler.KillByTag(tag); count += ProcessScheduler.KillByTag(tag);
count += _physicsScheduler.KillByTag(tag); count += PhysicsScheduler.KillByTag(tag);
count += _deferredScheduler.KillByTag(tag); count += DeferredScheduler.KillByTag(tag);
return count; return count;
} }
/// <summary>
/// 清空当前实例上的所有协程
/// 从所有调度器中清除协程
/// </summary>
/// <returns>被清除的协程总数</returns>
private int ClearOnInstance() private int ClearOnInstance()
{ {
int count = 0; int count = 0;
count += _processScheduler.Clear(); count += ProcessScheduler.Clear();
count += _physicsScheduler.Clear(); count += PhysicsScheduler.Clear();
count += _deferredScheduler.Clear(); count += DeferredScheduler.Clear();
return count; return count;
} }
@ -269,53 +413,25 @@ public partial class Timing : Node
#region #region
/// <summary>
/// 根据ID获取Timing实例
/// </summary>
/// <param name="id">实例ID</param>
/// <returns>对应的Timing实例或null</returns>
public static Timing? GetInstance(byte id) public static Timing? GetInstance(byte id)
{ {
return id < ActiveInstances.Length ? ActiveInstances[id] : null; return id < ActiveInstances.Length ? ActiveInstances[id] : null;
} }
/// <summary>
/// 创建等待指定秒数的指令
/// </summary>
public static Delay WaitForSeconds(double seconds)
{
return new Delay(seconds);
}
/// <summary> /// <summary>
/// 创建等待一帧的指令 /// 检查节点是否处于有效状态
/// </summary> /// </summary>
public static WaitOneFrame WaitForOneFrame() /// <param name="node">要检查的节点</param>
{ /// <returns>如果节点存在且有效则返回true否则返回false</returns>
return new WaitOneFrame();
}
/// <summary>
/// 创建等待指定帧数的指令
/// </summary>
public static WaitForFrames WaitForFrames(int frames)
{
return new WaitForFrames(frames);
}
/// <summary>
/// 创建等待直到条件满足的指令
/// </summary>
public static WaitUntil WaitUntil(Func<bool> predicate)
{
return new WaitUntil(predicate);
}
/// <summary>
/// 创建等待当条件为真时持续等待的指令
/// </summary>
public static WaitWhile WaitWhile(Func<bool> predicate)
{
return new WaitWhile(predicate);
}
public static bool IsNodeAlive(Node? node) public static bool IsNodeAlive(Node? node)
{ {
// 验证节点是否存在、实例是否有效、未被标记为删除且在场景树中
return node != null return node != null
&& IsInstanceValid(node) && IsInstanceValid(node)
&& !node.IsQueuedForDeletion() && !node.IsQueuedForDeletion()
@ -326,6 +442,13 @@ public partial class Timing : Node
#region #region
/// <summary>
/// 延迟调用指定动作
/// </summary>
/// <param name="delay">延迟时间(秒)</param>
/// <param name="action">要执行的动作</param>
/// <param name="segment">执行段</param>
/// <returns>协程句柄</returns>
public static CoroutineHandle CallDelayed( public static CoroutineHandle CallDelayed(
double delay, double delay,
Action? action, Action? action,
@ -337,6 +460,14 @@ public partial class Timing : Node
return RunCoroutine(DelayedCallCoroutine(delay, action), segment); return RunCoroutine(DelayedCallCoroutine(delay, action), segment);
} }
/// <summary>
/// 延迟调用指定动作,支持取消条件
/// </summary>
/// <param name="delay">延迟时间(秒)</param>
/// <param name="action">要执行的动作</param>
/// <param name="cancelWith">取消条件节点</param>
/// <param name="segment">执行段</param>
/// <returns>协程句柄</returns>
public static CoroutineHandle CallDelayed( public static CoroutineHandle CallDelayed(
double delay, double delay,
Action? action, Action? action,
@ -351,6 +482,12 @@ public partial class Timing : Node
segment); segment);
} }
/// <summary>
/// 延迟调用协程实现
/// </summary>
/// <param name="delay">延迟时间</param>
/// <param name="action">要执行的动作</param>
/// <returns>协程枚举器</returns>
private static IEnumerator<IYieldInstruction> DelayedCallCoroutine( private static IEnumerator<IYieldInstruction> DelayedCallCoroutine(
double delay, double delay,
Action action) Action action)
@ -359,6 +496,13 @@ public partial class Timing : Node
action(); action();
} }
/// <summary>
/// 带取消条件的延迟调用协程实现
/// </summary>
/// <param name="delay">延迟时间</param>
/// <param name="action">要执行的动作</param>
/// <param name="cancelWith">取消条件节点</param>
/// <returns>协程枚举器</returns>
private static IEnumerator<IYieldInstruction> DelayedCallWithCancelCoroutine( private static IEnumerator<IYieldInstruction> DelayedCallWithCancelCoroutine(
double delay, double delay,
Action action, Action action,