mirror of
https://github.com/GeWuYou/GFramework.git
synced 2026-03-22 10:34:30 +08:00
feat(coroutine): 添加多种协程等待指令及对应单元测试
- 实现 WaitForConditionChange 指令,支持等待条件状态变化 - 实现 WaitForEndOfFrame 指令,支持等待当前帧渲染完成 - 实现 WaitForFixedUpdate 指令,支持等待物理固定更新周期 - 实现 WaitForMultipleEvents 指令,支持等待多个事件中的任意一个触发 - 实现 WaitForNextFrame 指令,支持等待下一帧开始 - 实现 WaitForPredicate 指令,支持通用谓词等待功能 - 实现 WaitForSecondsRealtime 指令,支持基于真实时间的等待 - 实现 WaitForSecondsScaled 指令,支持受时间缩放影响的等待 - 实现 WaitUntilOrTimeout 指令,支持带超时的条件等待 - 为所有新指令添加完整的单元测试覆盖
This commit is contained in:
parent
6cc2bdfeb5
commit
4748198696
124
GFramework.Core.Tests/coroutine/WaitForConditionChangeTests.cs
Normal file
124
GFramework.Core.Tests/coroutine/WaitForConditionChangeTests.cs
Normal 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>());
|
||||
}
|
||||
}
|
||||
61
GFramework.Core.Tests/coroutine/WaitForEndOfFrameTests.cs
Normal file
61
GFramework.Core.Tests/coroutine/WaitForEndOfFrameTests.cs
Normal 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>());
|
||||
}
|
||||
}
|
||||
61
GFramework.Core.Tests/coroutine/WaitForFixedUpdateTests.cs
Normal file
61
GFramework.Core.Tests/coroutine/WaitForFixedUpdateTests.cs
Normal 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>());
|
||||
}
|
||||
}
|
||||
61
GFramework.Core.Tests/coroutine/WaitForNextFrameTests.cs
Normal file
61
GFramework.Core.Tests/coroutine/WaitForNextFrameTests.cs
Normal 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>());
|
||||
}
|
||||
}
|
||||
87
GFramework.Core.Tests/coroutine/WaitForPredicateTests.cs
Normal file
87
GFramework.Core.Tests/coroutine/WaitForPredicateTests.cs
Normal 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>());
|
||||
}
|
||||
}
|
||||
@ -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>());
|
||||
}
|
||||
}
|
||||
80
GFramework.Core.Tests/coroutine/WaitForSecondsScaledTests.cs
Normal file
80
GFramework.Core.Tests/coroutine/WaitForSecondsScaledTests.cs
Normal 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>());
|
||||
}
|
||||
}
|
||||
109
GFramework.Core.Tests/coroutine/WaitUntilOrTimeoutTests.cs
Normal file
109
GFramework.Core.Tests/coroutine/WaitUntilOrTimeoutTests.cs
Normal 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>());
|
||||
}
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
27
GFramework.Core/coroutine/instructions/WaitForEndOfFrame.cs
Normal file
27
GFramework.Core/coroutine/instructions/WaitForEndOfFrame.cs
Normal 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;
|
||||
}
|
||||
27
GFramework.Core/coroutine/instructions/WaitForFixedUpdate.cs
Normal file
27
GFramework.Core/coroutine/instructions/WaitForFixedUpdate.cs
Normal 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;
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
26
GFramework.Core/coroutine/instructions/WaitForNextFrame.cs
Normal file
26
GFramework.Core/coroutine/instructions/WaitForNextFrame.cs
Normal 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;
|
||||
}
|
||||
28
GFramework.Core/coroutine/instructions/WaitForPredicate.cs
Normal file
28
GFramework.Core/coroutine/instructions/WaitForPredicate.cs
Normal 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();
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
40
GFramework.Core/coroutine/instructions/WaitUntilOrTimeout.cs
Normal file
40
GFramework.Core/coroutine/instructions/WaitUntilOrTimeout.cs
Normal 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;
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user