Faster-Than-Real-Time & Deterministic Time Stepping
“Turn 60-second gameplay scenarios into 6-second CI runs.” Eliminate slow, flaky tests by controlling Unreal Engine's simulation speed, enforcing fixed physics ticks, and fast-forwarding long cooldowns in milliseconds.
Why It Matters
Gameplay automation tests are notoriously slow because game logic inherently depends on real wall-clock seconds: 60-second ultimate cooldowns, 10-second respawn timers, and 30-second capture points. Furthermore, varying hardware across developer laptops and CI machines causes variable frame rates, introducing physics flakiness and race conditions.
Specter solves both problems at the engine core by coupling Global Time Dilation with Fixed Delta Seconds.
How It Works
⚡ Global Time Dilation (timeDilation)
Accelerates the engine's entire simulation speed (e.g. 5.0 or 10.0) globally or per test, making 60 seconds of combat complete in 6 seconds.
🔒 Fixed Delta Time (fixedDeltaSeconds)
Locks physics and engine ticks to a constant step (e.g. 1 / 60 via r.FixedDeltaTime), ensuring identical, deterministic physics calculations across all CI runners.
⏩ world.advanceTime(seconds)
Directly steps the engine forward by N simulation seconds in a tight microsecond loop, instantly skipping long cooldowns without sleeping in real time.
⏱️ world.waitForGameSeconds()
Automatically scales the wall-clock sleep down based on active time dilation, ensuring predictable timing regardless of dilation settings.
Global Configuration
Set default time dilation and fixed delta time in your playwright.config.ts:
// playwright.config.ts
import { defineConfig } from "@playwright/test";
import type { SpecterTestOptions } from "@specter-automation/test";
export default defineConfig<SpecterTestOptions>({
use: {
timeDilation: 5.0, // Runs 5x faster than real-time
fixedDeltaSeconds: 1 / 60, // Deterministic 60 Hz physics step via r.FixedDeltaTime
},
});Fast-Forwarding Cooldowns in Tests
Override time dilation per test file or use world.advanceTime() to test cooldown recovery instantly:
import { test, expect } from "@specter-automation/test";
// Override time dilation for this entire test suite
test.use({ timeDilation: 10.0 });
test("Cooldown and buff expiration skips in ~500ms", async ({ world, steelActor }) => {
// Cast ultimate with a 60-second cooldown
await steelActor.triggerAbility("Ability.Slot.R");
// Fast-forward 60 in-game seconds in ~500ms of real wall-clock time!
await world.advanceTime(60.0);
// Ability is immediately ready again
await expect(steelActor).not.toHaveGameplayTag("Cooldown.Abilities.R");
});Scaled Waiting with waitForGameSeconds
// Scales wait down based on active time dilation automatically
// If timeDilation is 10.0, this completes in 300ms of real time!
await world.waitForGameSeconds(3.0);