feat(coroutine): 添加多种协程等待指令及对应单元测试

- 实现 WaitForConditionChange 指令,支持等待条件状态变化
- 实现 WaitForEndOfFrame 指令,支持等待当前帧渲染完成
- 实现 WaitForFixedUpdate 指令,支持等待物理固定更新周期
- 实现 WaitForMultipleEvents 指令,支持等待多个事件中的任意一个触发
- 实现 WaitForNextFrame 指令,支持等待下一帧开始
- 实现 WaitForPredicate 指令,支持通用谓词等待功能
- 实现 WaitForSecondsRealtime 指令,支持基于真实时间的等待
- 实现 WaitForSecondsScaled 指令,支持受时间缩放影响的等待
- 实现 WaitUntilOrTimeout 指令,支持带超时的条件等待
- 为所有新指令添加完整的单元测试覆盖
This commit is contained in:
GeWuYou 2026-02-10 23:14:00 +08:00 committed by gewuyou
parent 6cc2bdfeb5
commit 4748198696
17 changed files with 1016 additions and 0 deletions

View File

@ -0,0 +1,124 @@
using GFramework.Core.Abstractions.coroutine;
using GFramework.Core.coroutine.instructions;
using NUnit.Framework;
namespace GFramework.Core.Tests.coroutine;
/// <summary>
/// WaitForConditionChange的单元测试类
/// </summary>
[TestFixture]
public class WaitForConditionChangeTests
{
/// <summary>
/// 验证WaitForConditionChange初始状态为未完成
/// </summary>
[Test]
public void WaitForConditionChange_Should_Not_Be_Done_Initially()
{
var condition = false;
var wait = new WaitForConditionChange(() => condition, true);
Assert.That(wait.IsDone, Is.False);
}
/// <summary>
/// 验证WaitForConditionChange从false变为true时完成
/// </summary>
[Test]
public void WaitForConditionChange_Should_Be_Done_When_Changing_From_False_To_True()
{
var condition = false;
var wait = new WaitForConditionChange(() => condition, true);
// 初始状态记录
wait.Update(0.1);
condition = true;
wait.Update(0.1);
Assert.That(wait.IsDone, Is.True);
}
/// <summary>
/// 验证WaitForConditionChange从true变为false时完成
/// </summary>
[Test]
public void WaitForConditionChange_Should_Be_Done_When_Changing_From_True_To_False()
{
var condition = true;
var wait = new WaitForConditionChange(() => condition, false);
// 初始状态记录
wait.Update(0.1);
condition = false;
wait.Update(0.1);
Assert.That(wait.IsDone, Is.True);
}
/// <summary>
/// 验证WaitForConditionChange不响应相同状态的变化
/// </summary>
[Test]
public void WaitForConditionChange_Should_Not_Be_Done_When_No_State_Change()
{
var condition = false;
var wait = new WaitForConditionChange(() => condition, true);
// 初始状态记录
wait.Update(0.1);
// 仍然是false没有状态改变
wait.Update(0.1);
Assert.That(wait.IsDone, Is.False);
}
/// <summary>
/// 验证WaitForConditionChange多次状态切换只响应第一次
/// </summary>
[Test]
public void WaitForConditionChange_Should_Only_Respond_To_First_Transition()
{
var condition = false;
var wait = new WaitForConditionChange(() => condition, true);
// 记录初始状态
wait.Update(0.1);
Assert.That(wait.IsDone, Is.False);
// 触发状态转换到目标状态
condition = true;
wait.Update(0.1);
Assert.That(wait.IsDone, Is.True);
// 再次切换回原始状态
condition = false;
wait.Update(0.1);
// 应该仍然保持完成状态
Assert.That(wait.IsDone, Is.True);
}
/// <summary>
/// 验证WaitForConditionChange抛出ArgumentNullException当conditionGetter为null
/// </summary>
[Test]
public void WaitForConditionChange_Should_Throw_ArgumentNullException_When_ConditionGetter_Is_Null()
{
Assert.Throws<ArgumentNullException>(() => new WaitForConditionChange(null!, true));
}
/// <summary>
/// 验证WaitForConditionChange实现IYieldInstruction接口
/// </summary>
[Test]
public void WaitForConditionChange_Should_Implement_IYieldInstruction()
{
var wait = new WaitForConditionChange(() => false, true);
Assert.That(wait, Is.InstanceOf<IYieldInstruction>());
}
}

View File

@ -0,0 +1,61 @@
using GFramework.Core.Abstractions.coroutine;
using GFramework.Core.coroutine.instructions;
using NUnit.Framework;
namespace GFramework.Core.Tests.coroutine;
/// <summary>
/// WaitForEndOfFrame的单元测试类
/// </summary>
[TestFixture]
public class WaitForEndOfFrameTests
{
/// <summary>
/// 验证WaitForEndOfFrame初始状态为未完成
/// </summary>
[Test]
public void WaitForEndOfFrame_Should_Not_Be_Done_Initially()
{
var wait = new WaitForEndOfFrame();
Assert.That(wait.IsDone, Is.False);
}
/// <summary>
/// 验证WaitForEndOfFrame在Update后应该完成
/// </summary>
[Test]
public void WaitForEndOfFrame_Should_Be_Done_After_Update()
{
var wait = new WaitForEndOfFrame();
wait.Update(0.016);
Assert.That(wait.IsDone, Is.True);
}
/// <summary>
/// 验证WaitForEndOfFrame多次Update后仍保持完成状态
/// </summary>
[Test]
public void WaitForEndOfFrame_Should_Remain_Done_After_Multiple_Updates()
{
var wait = new WaitForEndOfFrame();
wait.Update(0.016);
Assert.That(wait.IsDone, Is.True);
wait.Update(0.016);
Assert.That(wait.IsDone, Is.True);
}
/// <summary>
/// 验证WaitForEndOfFrame实现IYieldInstruction接口
/// </summary>
[Test]
public void WaitForEndOfFrame_Should_Implement_IYieldInstruction()
{
var wait = new WaitForEndOfFrame();
Assert.That(wait, Is.InstanceOf<IYieldInstruction>());
}
}

View File

@ -0,0 +1,61 @@
using GFramework.Core.Abstractions.coroutine;
using GFramework.Core.coroutine.instructions;
using NUnit.Framework;
namespace GFramework.Core.Tests.coroutine;
/// <summary>
/// WaitForFixedUpdate的单元测试类
/// </summary>
[TestFixture]
public class WaitForFixedUpdateTests
{
/// <summary>
/// 验证WaitForFixedUpdate初始状态为未完成
/// </summary>
[Test]
public void WaitForFixedUpdate_Should_Not_Be_Done_Initially()
{
var wait = new WaitForFixedUpdate();
Assert.That(wait.IsDone, Is.False);
}
/// <summary>
/// 验证WaitForFixedUpdate在Update后应该完成
/// </summary>
[Test]
public void WaitForFixedUpdate_Should_Be_Done_After_Update()
{
var wait = new WaitForFixedUpdate();
wait.Update(0.016);
Assert.That(wait.IsDone, Is.True);
}
/// <summary>
/// 验证WaitForFixedUpdate多次Update后仍保持完成状态
/// </summary>
[Test]
public void WaitForFixedUpdate_Should_Remain_Done_After_Multiple_Updates()
{
var wait = new WaitForFixedUpdate();
wait.Update(0.016);
Assert.That(wait.IsDone, Is.True);
wait.Update(0.016);
Assert.That(wait.IsDone, Is.True);
}
/// <summary>
/// 验证WaitForFixedUpdate实现IYieldInstruction接口
/// </summary>
[Test]
public void WaitForFixedUpdate_Should_Implement_IYieldInstruction()
{
var wait = new WaitForFixedUpdate();
Assert.That(wait, Is.InstanceOf<IYieldInstruction>());
}
}

View File

@ -0,0 +1,61 @@
using GFramework.Core.Abstractions.coroutine;
using GFramework.Core.coroutine.instructions;
using NUnit.Framework;
namespace GFramework.Core.Tests.coroutine;
/// <summary>
/// WaitForNextFrame的单元测试类
/// </summary>
[TestFixture]
public class WaitForNextFrameTests
{
/// <summary>
/// 验证WaitForNextFrame初始状态为未完成
/// </summary>
[Test]
public void WaitForNextFrame_Should_Not_Be_Done_Initially()
{
var wait = new WaitForNextFrame();
Assert.That(wait.IsDone, Is.False);
}
/// <summary>
/// 验证WaitForNextFrame在Update后应该完成
/// </summary>
[Test]
public void WaitForNextFrame_Should_Be_Done_After_Update()
{
var wait = new WaitForNextFrame();
wait.Update(0.016);
Assert.That(wait.IsDone, Is.True);
}
/// <summary>
/// 验证WaitForNextFrame多次Update后仍保持完成状态
/// </summary>
[Test]
public void WaitForNextFrame_Should_Remain_Done_After_Multiple_Updates()
{
var wait = new WaitForNextFrame();
wait.Update(0.016);
Assert.That(wait.IsDone, Is.True);
wait.Update(0.016);
Assert.That(wait.IsDone, Is.True);
}
/// <summary>
/// 验证WaitForNextFrame实现IYieldInstruction接口
/// </summary>
[Test]
public void WaitForNextFrame_Should_Implement_IYieldInstruction()
{
var wait = new WaitForNextFrame();
Assert.That(wait, Is.InstanceOf<IYieldInstruction>());
}
}

View File

@ -0,0 +1,87 @@
using GFramework.Core.Abstractions.coroutine;
using GFramework.Core.coroutine.instructions;
using NUnit.Framework;
namespace GFramework.Core.Tests.coroutine;
/// <summary>
/// WaitForPredicate的单元测试类
/// </summary>
[TestFixture]
public class WaitForPredicateTests
{
/// <summary>
/// 验证WaitForPredicate默认等待条件为真时完成
/// </summary>
[Test]
public void WaitForPredicate_Should_Wait_For_True_By_Default()
{
var condition = false;
var wait = new WaitForPredicate(() => condition);
Assert.That(wait.IsDone, Is.False);
condition = true;
Assert.That(wait.IsDone, Is.True);
}
/// <summary>
/// 验证WaitForPredicate可以等待条件为假时完成
/// </summary>
[Test]
public void WaitForPredicate_Should_Wait_For_False_When_Specified()
{
var condition = true;
var wait = new WaitForPredicate(() => condition, false);
Assert.That(wait.IsDone, Is.False);
condition = false;
Assert.That(wait.IsDone, Is.True);
}
/// <summary>
/// 验证WaitForPredicate多次检查条件
/// </summary>
[Test]
public void WaitForPredicate_Should_Check_Condition_Multiple_Times()
{
var callCount = 0;
var wait = new WaitForPredicate(() =>
{
callCount++;
return callCount >= 3;
});
Assert.That(wait.IsDone, Is.False);
Assert.That(callCount, Is.EqualTo(1));
wait.Update(0.1);
Assert.That(wait.IsDone, Is.False);
Assert.That(callCount, Is.EqualTo(2));
wait.Update(0.1);
Assert.That(wait.IsDone, Is.True);
Assert.That(callCount, Is.EqualTo(3));
}
/// <summary>
/// 验证WaitForPredicate抛出ArgumentNullException当predicate为null
/// </summary>
[Test]
public void WaitForPredicate_Should_Throw_ArgumentNullException_When_Predicate_Is_Null()
{
Assert.Throws<ArgumentNullException>(() => new WaitForPredicate(null!));
}
/// <summary>
/// 验证WaitForPredicate实现IYieldInstruction接口
/// </summary>
[Test]
public void WaitForPredicate_Should_Implement_IYieldInstruction()
{
var wait = new WaitForPredicate(() => true);
Assert.That(wait, Is.InstanceOf<IYieldInstruction>());
}
}

View File

@ -0,0 +1,80 @@
using GFramework.Core.Abstractions.coroutine;
using GFramework.Core.coroutine.instructions;
using NUnit.Framework;
namespace GFramework.Core.Tests.coroutine;
/// <summary>
/// WaitForSecondsRealtime的单元测试类
/// </summary>
[TestFixture]
public class WaitForSecondsRealtimeTests
{
/// <summary>
/// 验证WaitForSecondsRealtime初始状态根据时间设置
/// </summary>
[Test]
public void WaitForSecondsRealtime_Should_Handle_Initial_State_Correctly()
{
var waitZero = new WaitForSecondsRealtime(0);
var waitPositive = new WaitForSecondsRealtime(1.0);
Assert.That(waitZero.IsDone, Is.True);
Assert.That(waitPositive.IsDone, Is.False);
}
/// <summary>
/// 验证WaitForSecondsRealtime应该在指定时间后完成
/// </summary>
[Test]
public void WaitForSecondsRealtime_Should_Be_Done_After_Specified_Time()
{
var wait = new WaitForSecondsRealtime(1.0);
wait.Update(0.5);
Assert.That(wait.IsDone, Is.False);
wait.Update(0.5);
Assert.That(wait.IsDone, Is.True);
}
/// <summary>
/// 验证WaitForSecondsRealtime可以处理负数时间
/// </summary>
[Test]
public void WaitForSecondsRealtime_Should_Handle_Negative_Time()
{
var wait = new WaitForSecondsRealtime(-1.0);
Assert.That(wait.IsDone, Is.True);
}
/// <summary>
/// 验证WaitForSecondsRealtime多次更新累积时间
/// </summary>
[Test]
public void WaitForSecondsRealtime_Should_Accumulate_Time_Over_Multiple_Updates()
{
var wait = new WaitForSecondsRealtime(2.0);
wait.Update(0.5);
Assert.That(wait.IsDone, Is.False);
wait.Update(1.0);
Assert.That(wait.IsDone, Is.False);
wait.Update(0.5);
Assert.That(wait.IsDone, Is.True);
}
/// <summary>
/// 验证WaitForSecondsRealtime实现IYieldInstruction接口
/// </summary>
[Test]
public void WaitForSecondsRealtime_Should_Implement_IYieldInstruction()
{
var wait = new WaitForSecondsRealtime(1.0);
Assert.That(wait, Is.InstanceOf<IYieldInstruction>());
}
}

View File

@ -0,0 +1,80 @@
using GFramework.Core.Abstractions.coroutine;
using GFramework.Core.coroutine.instructions;
using NUnit.Framework;
namespace GFramework.Core.Tests.coroutine;
/// <summary>
/// WaitForSecondsScaled的单元测试类
/// </summary>
[TestFixture]
public class WaitForSecondsScaledTests
{
/// <summary>
/// 验证WaitForSecondsScaled初始状态根据时间设置
/// </summary>
[Test]
public void WaitForSecondsScaled_Should_Handle_Initial_State_Correctly()
{
var waitZero = new WaitForSecondsScaled(0);
var waitPositive = new WaitForSecondsScaled(1.0);
Assert.That(waitZero.IsDone, Is.True);
Assert.That(waitPositive.IsDone, Is.False);
}
/// <summary>
/// 验证WaitForSecondsScaled应该在指定时间后完成
/// </summary>
[Test]
public void WaitForSecondsScaled_Should_Be_Done_After_Specified_Time()
{
var wait = new WaitForSecondsScaled(1.0);
wait.Update(0.5);
Assert.That(wait.IsDone, Is.False);
wait.Update(0.5);
Assert.That(wait.IsDone, Is.True);
}
/// <summary>
/// 验证WaitForSecondsScaled可以处理负数时间
/// </summary>
[Test]
public void WaitForSecondsScaled_Should_Handle_Negative_Time()
{
var wait = new WaitForSecondsScaled(-1.0);
Assert.That(wait.IsDone, Is.True);
}
/// <summary>
/// 验证WaitForSecondsScaled多次更新累积时间
/// </summary>
[Test]
public void WaitForSecondsScaled_Should_Accumulate_Time_Over_Multiple_Updates()
{
var wait = new WaitForSecondsScaled(2.0);
wait.Update(0.5);
Assert.That(wait.IsDone, Is.False);
wait.Update(1.0);
Assert.That(wait.IsDone, Is.False);
wait.Update(0.5);
Assert.That(wait.IsDone, Is.True);
}
/// <summary>
/// 验证WaitForSecondsScaled实现IYieldInstruction接口
/// </summary>
[Test]
public void WaitForSecondsScaled_Should_Implement_IYieldInstruction()
{
var wait = new WaitForSecondsScaled(1.0);
Assert.That(wait, Is.InstanceOf<IYieldInstruction>());
}
}

View File

@ -0,0 +1,109 @@
using GFramework.Core.Abstractions.coroutine;
using GFramework.Core.coroutine.instructions;
using NUnit.Framework;
namespace GFramework.Core.Tests.coroutine;
/// <summary>
/// WaitUntilOrTimeout的单元测试类
/// </summary>
[TestFixture]
public class WaitUntilOrTimeoutTests
{
/// <summary>
/// 验证WaitUntilOrTimeout初始状态为未完成
/// </summary>
[Test]
public void WaitUntilOrTimeout_Should_Not_Be_Done_Initially()
{
var condition = false;
var wait = new WaitUntilOrTimeout(() => condition, 5.0);
Assert.That(wait.IsDone, Is.False);
Assert.That(wait.ConditionMet, Is.False);
Assert.That(wait.IsTimedOut, Is.False);
}
/// <summary>
/// 验证WaitUntilOrTimeout应该在条件满足时完成
/// </summary>
[Test]
public void WaitUntilOrTimeout_Should_Be_Done_When_Condition_Met()
{
var condition = false;
var wait = new WaitUntilOrTimeout(() => condition, 5.0);
condition = true;
wait.Update(0.1);
Assert.That(wait.IsDone, Is.True);
Assert.That(wait.ConditionMet, Is.True);
Assert.That(wait.IsTimedOut, Is.False);
}
/// <summary>
/// 验证WaitUntilOrTimeout应该在超时时完成
/// </summary>
[Test]
public void WaitUntilOrTimeout_Should_Be_Done_When_Timed_Out()
{
var condition = false;
var wait = new WaitUntilOrTimeout(() => condition, 1.0);
wait.Update(1.5);
Assert.That(wait.IsDone, Is.True);
Assert.That(wait.ConditionMet, Is.False);
Assert.That(wait.IsTimedOut, Is.True);
}
/// <summary>
/// 验证WaitUntilOrTimeout可以处理零超时时间
/// </summary>
[Test]
public void WaitUntilOrTimeout_Should_Handle_Zero_Timeout()
{
var condition = false;
var wait = new WaitUntilOrTimeout(() => condition, 0);
wait.Update(0.1);
Assert.That(wait.IsDone, Is.True);
Assert.That(wait.IsTimedOut, Is.True);
}
/// <summary>
/// 验证WaitUntilOrTimeout可以处理负数超时时间
/// </summary>
[Test]
public void WaitUntilOrTimeout_Should_Handle_Negative_Timeout()
{
var condition = false;
var wait = new WaitUntilOrTimeout(() => condition, -1.0);
wait.Update(0.1);
Assert.That(wait.IsDone, Is.True);
Assert.That(wait.IsTimedOut, Is.True);
}
/// <summary>
/// 验证WaitUntilOrTimeout抛出ArgumentNullException当predicate为null
/// </summary>
[Test]
public void WaitUntilOrTimeout_Should_Throw_ArgumentNullException_When_Predicate_Is_Null()
{
Assert.Throws<ArgumentNullException>(() => new WaitUntilOrTimeout(null!, 1.0));
}
/// <summary>
/// 验证WaitUntilOrTimeout实现IYieldInstruction接口
/// </summary>
[Test]
public void WaitUntilOrTimeout_Should_Implement_IYieldInstruction()
{
var wait = new WaitUntilOrTimeout(() => false, 1.0);
Assert.That(wait, Is.InstanceOf<IYieldInstruction>());
}
}

View File

@ -0,0 +1,46 @@
using GFramework.Core.Abstractions.coroutine;
namespace GFramework.Core.coroutine.instructions;
/// <summary>
/// 等待条件状态发生变化的指令
/// 当条件从一种状态切换到另一种状态时完成
/// </summary>
/// <param name="conditionGetter">获取当前条件状态的函数</param>
/// <param name="waitForTransitionTo">期望转换到的目标状态</param>
public sealed class WaitForConditionChange(Func<bool> conditionGetter, bool waitForTransitionTo) : IYieldInstruction
{
private readonly Func<bool> _conditionGetter =
conditionGetter ?? throw new ArgumentNullException(nameof(conditionGetter));
private bool? _initialState;
private bool _isCompleted;
/// <summary>
/// 更新方法,检测条件变化
/// </summary>
/// <param name="deltaTime">时间增量</param>
public void Update(double deltaTime)
{
if (_isCompleted)
return;
if (!_initialState.HasValue)
{
_initialState = _conditionGetter();
return;
}
// 检查是否发生了期望的状态转换
var currentState = _conditionGetter();
if (currentState == waitForTransitionTo && _initialState.Value != waitForTransitionTo)
{
_isCompleted = true;
}
}
/// <summary>
/// 获取等待是否已完成(条件发生了期望的状态转换)
/// </summary>
public bool IsDone => _isCompleted;
}

View File

@ -0,0 +1,27 @@
using GFramework.Core.Abstractions.coroutine;
namespace GFramework.Core.coroutine.instructions;
/// <summary>
/// 等待当前帧渲染完成的指令
/// 通常用于需要在渲染完成后执行的操作
/// </summary>
public sealed class WaitForEndOfFrame : IYieldInstruction
{
private bool _completed;
/// <summary>
/// 更新方法,在帧末尾被调用
/// </summary>
/// <param name="deltaTime">时间增量</param>
public void Update(double deltaTime)
{
// 在帧结束时标记完成
_completed = true;
}
/// <summary>
/// 获取等待是否已完成
/// </summary>
public bool IsDone => _completed;
}

View File

@ -0,0 +1,27 @@
using GFramework.Core.Abstractions.coroutine;
namespace GFramework.Core.coroutine.instructions;
/// <summary>
/// 等待下一个物理固定更新周期的指令
/// 主要用于需要与物理系统同步的操作
/// </summary>
public sealed class WaitForFixedUpdate : IYieldInstruction
{
private bool _completed;
/// <summary>
/// 更新方法,在固定更新时被调用
/// </summary>
/// <param name="deltaTime">时间增量</param>
public void Update(double deltaTime)
{
// 在固定更新周期中标记完成
_completed = true;
}
/// <summary>
/// 获取等待是否已完成
/// </summary>
public bool IsDone => _completed;
}

View File

@ -0,0 +1,99 @@
using GFramework.Core.Abstractions.coroutine;
using GFramework.Core.Abstractions.events;
namespace GFramework.Core.coroutine.instructions;
/// <summary>
/// 等待多个事件中的任意一个触发的指令
/// 实现了 IDisposable 接口,支持资源释放
/// </summary>
/// <typeparam name="TEvent1">第一个事件类型</typeparam>
/// <typeparam name="TEvent2">第二个事件类型</typeparam>
public sealed class WaitForMultipleEvents<TEvent1, TEvent2> : IYieldInstruction, IDisposable
{
private bool _disposed;
private volatile bool _done;
private IUnRegister? _unRegister1;
private IUnRegister? _unRegister2;
/// <summary>
/// 初始化 WaitForMultipleEvents 实例
/// </summary>
/// <param name="eventBus">事件总线实例</param>
public WaitForMultipleEvents(IEventBus eventBus)
{
var eventBus1 = eventBus ?? throw new ArgumentNullException(nameof(eventBus));
// 注册两个事件的监听器
_unRegister1 = eventBus1.Register<TEvent1>(OnFirstEvent);
_unRegister2 = eventBus1.Register<TEvent2>(OnSecondEvent);
}
/// <summary>
/// 获取第一个事件的数据(如果已触发)
/// </summary>
public TEvent1? FirstEventData { get; private set; }
/// <summary>
/// 获取第二个事件的数据(如果已触发)
/// </summary>
public TEvent2? SecondEventData { get; private set; }
/// <summary>
/// 获取是哪个事件先触发1表示第一个事件2表示第二个事件
/// </summary>
public int TriggeredBy { get; private set; }
/// <summary>
/// 释放资源
/// </summary>
public void Dispose()
{
if (_disposed) return;
_unRegister1?.UnRegister();
_unRegister2?.UnRegister();
_unRegister1 = null;
_unRegister2 = null;
_disposed = true;
}
/// <summary>
/// 获取等待是否已完成
/// </summary>
public bool IsDone => _done;
/// <summary>
/// 更新方法
/// </summary>
/// <param name="deltaTime">时间增量</param>
public void Update(double deltaTime)
{
if (!_done || (_unRegister1 == null && _unRegister2 == null)) return;
_unRegister1?.UnRegister();
_unRegister2?.UnRegister();
_unRegister1 = null;
_unRegister2 = null;
}
/// <summary>
/// 第一个事件触发处理
/// </summary>
private void OnFirstEvent(TEvent1 eventData)
{
FirstEventData = eventData;
TriggeredBy = 1;
_done = true;
}
/// <summary>
/// 第二个事件触发处理
/// </summary>
private void OnSecondEvent(TEvent2 eventData)
{
SecondEventData = eventData;
TriggeredBy = 2;
_done = true;
}
}

View File

@ -0,0 +1,26 @@
using GFramework.Core.Abstractions.coroutine;
namespace GFramework.Core.coroutine.instructions;
/// <summary>
/// 等待下一帧的指令与WaitOneFrame功能相同提供另一种命名选择
/// 用于需要明确表达"等待到下一帧开始"的场景
/// </summary>
public sealed class WaitForNextFrame : IYieldInstruction
{
private bool _completed;
/// <summary>
/// 更新方法在下一帧被调用时将完成状态设置为true
/// </summary>
/// <param name="deltaTime">时间间隔</param>
public void Update(double deltaTime)
{
_completed = true;
}
/// <summary>
/// 获取当前等待指令是否已完成
/// </summary>
public bool IsDone => _completed;
}

View File

@ -0,0 +1,28 @@
using GFramework.Core.Abstractions.coroutine;
namespace GFramework.Core.coroutine.instructions;
/// <summary>
/// 通用谓词等待指令
/// 支持自定义比较逻辑,可以替代 WaitUntil 和 WaitWhile
/// </summary>
/// <param name="predicate">条件判断函数</param>
/// <param name="waitForTrue">true表示等待条件为真时完成false表示等待条件为假时完成</param>
public sealed class WaitForPredicate(Func<bool> predicate, bool waitForTrue = true) : IYieldInstruction
{
private readonly Func<bool> _predicate = predicate ?? throw new ArgumentNullException(nameof(predicate));
/// <summary>
/// 更新协程状态
/// </summary>
/// <param name="deltaTime">时间增量</param>
public void Update(double deltaTime)
{
// 不需要特殊处理时间
}
/// <summary>
/// 获取协程指令是否已完成
/// </summary>
public bool IsDone => waitForTrue ? _predicate() : !_predicate();
}

View File

@ -0,0 +1,30 @@
using GFramework.Core.Abstractions.coroutine;
namespace GFramework.Core.coroutine.instructions;
/// <summary>
/// 基于真实时间的等待指令(不受时间缩放影响)
/// 适用于需要精确计时的场景如UI动画、计时器等
/// </summary>
/// <param name="seconds">需要等待的秒数</param>
public sealed class WaitForSecondsRealtime(double seconds) : IYieldInstruction
{
/// <summary>
/// 剩余等待时间(真实时间)
/// </summary>
private double _remaining = Math.Max(0, seconds);
/// <summary>
/// 更新延迟计时器(使用真实时间)
/// </summary>
/// <param name="deltaTime">时间增量</param>
public void Update(double deltaTime)
{
_remaining -= deltaTime;
}
/// <summary>
/// 获取延迟是否完成
/// </summary>
public bool IsDone => _remaining <= 0;
}

View File

@ -0,0 +1,30 @@
using GFramework.Core.Abstractions.coroutine;
namespace GFramework.Core.coroutine.instructions;
/// <summary>
/// 受时间缩放影响的等待指令
/// 明确表示会受到游戏时间缩放的影响
/// </summary>
/// <param name="seconds">需要等待的秒数</param>
public sealed class WaitForSecondsScaled(double seconds) : IYieldInstruction
{
/// <summary>
/// 剩余等待时间(受时间缩放影响)
/// </summary>
private double _remaining = Math.Max(0, seconds);
/// <summary>
/// 更新延迟计时器(受时间缩放影响)
/// </summary>
/// <param name="deltaTime">时间增量</param>
public void Update(double deltaTime)
{
_remaining -= deltaTime;
}
/// <summary>
/// 获取延迟是否完成
/// </summary>
public bool IsDone => _remaining <= 0;
}

View File

@ -0,0 +1,40 @@
using GFramework.Core.Abstractions.coroutine;
namespace GFramework.Core.coroutine.instructions;
/// <summary>
/// 带超时的条件等待指令
/// 当条件满足或超时时间到达时完成
/// </summary>
/// <param name="predicate">条件判断函数</param>
/// <param name="timeoutSeconds">超时时间(秒)</param>
public sealed class WaitUntilOrTimeout(Func<bool> predicate, double timeoutSeconds) : IYieldInstruction
{
private readonly Func<bool> _predicate = predicate ?? throw new ArgumentNullException(nameof(predicate));
private readonly double _timeout = Math.Max(0, timeoutSeconds);
private double _elapsedTime;
/// <summary>
/// 获取是否因条件满足而完成
/// </summary>
public bool ConditionMet => _predicate();
/// <summary>
/// 获取是否因超时而完成
/// </summary>
public bool IsTimedOut => _elapsedTime >= _timeout;
/// <summary>
/// 更新方法,累计时间和检查条件
/// </summary>
/// <param name="deltaTime">时间增量</param>
public void Update(double deltaTime)
{
_elapsedTime += deltaTime;
}
/// <summary>
/// 获取等待是否已完成(条件满足或超时)
/// </summary>
public bool IsDone => ConditionMet || IsTimedOut;
}