diff --git a/GFramework.Godot/coroutine/Segment.cs b/GFramework.Godot/coroutine/Segment.cs
index 8ed2fb6..5d4cc50 100644
--- a/GFramework.Godot/coroutine/Segment.cs
+++ b/GFramework.Godot/coroutine/Segment.cs
@@ -6,10 +6,15 @@
public enum Segment
{
///
- /// 普通处理阶段,在每一帧的常规处理过程中执行
+ /// 普通处理阶段,在每一帧的常规处理过程中执行(默认用于游戏级协程)
///
Process,
+ ///
+ /// 在暂停状态下仍然执行的处理阶段,适合暂停菜单等需要继续更新的UI级协程
+ ///
+ ProcessIgnorePause,
+
///
/// 物理处理阶段,在物理更新循环中执行,通常用于需要与物理引擎同步的操作
///
@@ -19,4 +24,4 @@ public enum Segment
/// 延迟处理阶段,在当前帧结束后延迟执行,通常用于需要等待当前帧完成后再执行的操作
///
DeferredProcess
-}
\ No newline at end of file
+}
diff --git a/GFramework.Godot/coroutine/Timing.cs b/GFramework.Godot/coroutine/Timing.cs
index 9a5a2d2..29fdf6c 100644
--- a/GFramework.Godot/coroutine/Timing.cs
+++ b/GFramework.Godot/coroutine/Timing.cs
@@ -26,6 +26,8 @@ public partial class Timing : Node
private CoroutineScheduler? _processScheduler;
private GodotTimeSource? _processTimeSource;
+ private CoroutineScheduler? _processIgnorePauseScheduler;
+ private GodotTimeSource? _processIgnorePauseTimeSource;
///
/// 获取Process调度器,如果未初始化则抛出异常
@@ -34,6 +36,13 @@ public partial class Timing : Node
_processScheduler ?? throw new InvalidOperationException(
"Timing not yet initialized (_Ready not executed)");
+ ///
+ /// 获取忽略暂停的Process调度器,如果未初始化则抛出异常
+ ///
+ private CoroutineScheduler ProcessIgnorePauseScheduler =>
+ _processIgnorePauseScheduler ?? throw new InvalidOperationException(
+ "Timing not yet initialized (_Ready not executed)");
+
///
/// 获取Physics调度器,如果未初始化则抛出异常
///
@@ -108,6 +117,7 @@ public partial class Timing : Node
public override void _Ready()
{
ProcessPriority = -1;
+ ProcessMode = ProcessModeEnum.Always;
TrySetPhysicsPriority(-1);
@@ -142,7 +152,12 @@ public partial class Timing : Node
/// 时间增量
public override void _Process(double delta)
{
- _processScheduler?.Update();
+ var paused = GetTree().Paused;
+
+ if (!paused)
+ _processScheduler?.Update();
+
+ _processIgnorePauseScheduler?.Update();
_frameCounter++;
CallDeferred(nameof(ProcessDeferred));
@@ -164,6 +179,9 @@ public partial class Timing : Node
///
private void ProcessDeferred()
{
+ if (GetTree().Paused)
+ return;
+
_deferredScheduler?.Update();
}
@@ -187,6 +205,7 @@ public partial class Timing : Node
private void InitializeSchedulers()
{
_processTimeSource = new GodotTimeSource(GetProcessDeltaTime);
+ _processIgnorePauseTimeSource = new GodotTimeSource(GetProcessDeltaTime);
_physicsTimeSource = new GodotTimeSource(GetPhysicsProcessDeltaTime);
_deferredTimeSource = new GodotTimeSource(GetProcessDeltaTime);
@@ -195,6 +214,11 @@ public partial class Timing : Node
_instanceId
);
+ _processIgnorePauseScheduler = new CoroutineScheduler(
+ _processIgnorePauseTimeSource,
+ _instanceId
+ );
+
_physicsScheduler = new CoroutineScheduler(
_physicsTimeSource,
_instanceId,
@@ -206,6 +230,7 @@ public partial class Timing : Node
_instanceId,
64
);
+
}
///
@@ -257,6 +282,32 @@ public partial class Timing : Node
#region 协程启动 API
+ ///
+ /// 运行游戏级协程(受暂停影响)
+ ///
+ /// 要运行的协程枚举器
+ /// 协程标签,用于批量操作
+ /// 协程句柄
+ public static CoroutineHandle RunGameCoroutine(
+ IEnumerator coroutine,
+ string? tag = null)
+ {
+ return RunCoroutine(coroutine, Segment.Process, tag);
+ }
+
+ ///
+ /// 运行UI级协程(忽略暂停)
+ ///
+ /// 要运行的协程枚举器
+ /// 协程标签,用于批量操作
+ /// 协程句柄
+ public static CoroutineHandle RunUiCoroutine(
+ IEnumerator coroutine,
+ string? tag = null)
+ {
+ return RunCoroutine(coroutine, Segment.ProcessIgnorePause, tag);
+ }
+
///
/// 在指定段运行协程
///
@@ -291,6 +342,7 @@ public partial class Timing : Node
return segment switch
{
Segment.Process => ProcessScheduler.Run(coroutine, tag),
+ Segment.ProcessIgnorePause => ProcessIgnorePauseScheduler.Run(coroutine, tag),
Segment.PhysicsProcess => PhysicsScheduler.Run(coroutine, tag),
Segment.DeferredProcess => DeferredScheduler.Run(coroutine, tag),
_ => default
@@ -359,6 +411,7 @@ public partial class Timing : Node
private bool PauseOnInstance(CoroutineHandle handle)
{
return ProcessScheduler.Pause(handle)
+ || ProcessIgnorePauseScheduler.Pause(handle)
|| PhysicsScheduler.Pause(handle)
|| DeferredScheduler.Pause(handle);
}
@@ -372,6 +425,7 @@ public partial class Timing : Node
private bool ResumeOnInstance(CoroutineHandle handle)
{
return ProcessScheduler.Resume(handle)
+ || ProcessIgnorePauseScheduler.Resume(handle)
|| PhysicsScheduler.Resume(handle)
|| DeferredScheduler.Resume(handle);
}
@@ -385,6 +439,7 @@ public partial class Timing : Node
private bool KillOnInstance(CoroutineHandle handle)
{
return ProcessScheduler.Kill(handle)
+ || ProcessIgnorePauseScheduler.Kill(handle)
|| PhysicsScheduler.Kill(handle)
|| DeferredScheduler.Kill(handle);
}
@@ -399,6 +454,7 @@ public partial class Timing : Node
{
var count = 0;
count += ProcessScheduler.KillByTag(tag);
+ count += ProcessIgnorePauseScheduler.KillByTag(tag);
count += PhysicsScheduler.KillByTag(tag);
count += DeferredScheduler.KillByTag(tag);
return count;
@@ -413,6 +469,7 @@ public partial class Timing : Node
{
var count = 0;
count += ProcessScheduler.Clear();
+ count += ProcessIgnorePauseScheduler.Clear();
count += PhysicsScheduler.Clear();
count += DeferredScheduler.Clear();
return count;
@@ -524,4 +581,4 @@ public partial class Timing : Node
}
#endregion
-}
\ No newline at end of file
+}