Both were explicitly deferred to M4 by ITime and Stage's own doc comments back when they were written: a FixedUpdate stage with no real accumulator behind it would be actively misleading, and building the accumulator with no physics system to test it against would be untested speculative machinery. engine.physics (next) is the real consumer. Time.ConsumeFixedSteps accumulates DeltaTime and hands back how many FixedDeltaTime-sized (1/50s) steps it can pay for, capped at 5 per frame so a real stall becomes visible lag instead of a catch-up burst of physics steps. Engine.Host calls it once per frame in both the headless and windowed loops, running Stage.FixedUpdate that many times before Stage.Update — gated by IPlayModeController.IsPlaying the same way Update already is, and only accumulating time while actually playing, so entering Play doesn't open with a burst of steps for however long Edit mode had been sitting idle. 3 new tests on the accumulator itself (below-one-step, whole-steps-plus- remainder, the 5-step cap under a simulated stall). Full suite: 76 tests. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01N1qPfzq8TDCUMFMV3UwV5N
75 lines
1.7 KiB
C#
75 lines
1.7 KiB
C#
using Engine.Kernel.Diagnostics;
|
|
|
|
namespace Engine.Kernel.Tests;
|
|
|
|
public class TimeTests
|
|
{
|
|
[Fact]
|
|
public void Starts_At_Zero()
|
|
{
|
|
var time = new Time();
|
|
|
|
Assert.Equal(0, time.DeltaTime);
|
|
Assert.Equal(0, time.ElapsedTime);
|
|
Assert.Equal(0, time.FrameCount);
|
|
}
|
|
|
|
[Fact]
|
|
public void Tick_Sets_DeltaTime_And_Advances_ElapsedTime_And_FrameCount()
|
|
{
|
|
var time = new Time();
|
|
|
|
time.Tick(0.5f);
|
|
|
|
Assert.Equal(0.5f, time.DeltaTime);
|
|
Assert.Equal(0.5, time.ElapsedTime, 3);
|
|
Assert.Equal(1, time.FrameCount);
|
|
}
|
|
|
|
[Fact]
|
|
public void ElapsedTime_And_FrameCount_Accumulate_Across_Ticks()
|
|
{
|
|
var time = new Time();
|
|
|
|
time.Tick(0.5f);
|
|
time.Tick(0.25f);
|
|
|
|
Assert.Equal(0.25f, time.DeltaTime);
|
|
Assert.Equal(0.75, time.ElapsedTime, 3);
|
|
Assert.Equal(2, time.FrameCount);
|
|
}
|
|
|
|
[Fact]
|
|
public void ConsumeFixedSteps_BelowOneStep_ReturnsZero()
|
|
{
|
|
var time = new Time();
|
|
|
|
// FixedDeltaTime is 1/50 = 0.02s; a 60fps-ish frame is shorter.
|
|
time.Tick(0.01f);
|
|
|
|
Assert.Equal(0, time.ConsumeFixedSteps());
|
|
}
|
|
|
|
[Fact]
|
|
public void ConsumeFixedSteps_ConsumesWholeStepsAndKeepsRemainder()
|
|
{
|
|
var time = new Time();
|
|
|
|
time.Tick(0.05f); // 2.5 steps' worth
|
|
Assert.Equal(2, time.ConsumeFixedSteps());
|
|
|
|
time.Tick(0.03f); // remainder 0.01 + 0.03 = 0.04 -> 2 more steps
|
|
Assert.Equal(2, time.ConsumeFixedSteps());
|
|
}
|
|
|
|
[Fact]
|
|
public void ConsumeFixedSteps_CapsAtFiveEvenAfterAHugeStall()
|
|
{
|
|
var time = new Time();
|
|
|
|
time.Tick(10f); // a debugger pause, not a real frame
|
|
|
|
Assert.Equal(5, time.ConsumeFixedSteps());
|
|
}
|
|
}
|