Use when writing acceptance criteria for a task - express each as an observable Given/When/Then that QA can execute, including negative cases
中文简介正在准备中。当前显示原文说明。
Use when writing anything that moves, animates, counts down or simulates - per-frame vs fixed-step callbacks per engine, the accumulator loop with interpolation, delta-scaled smoothing, pause and time scale, and determinism.
中文简介正在准备中。当前显示原文说明。
查看安装方法安装前可以查看交给 AI 代理的指令内容。
Two clocks run in every game: the render frame (variable, as fast as the machine allows) and the simulation step (fixed, so physics and rules behave the same everywhere). Most "it moves faster on my machine", tunnelling, jitter and desync bugs come from putting work on the wrong clock or forgetting to scale by the right delta.
Core principle: Simulate on a fixed step, render with interpolation, and scale every time-based value by the delta of the clock it runs on.
| Engine | Per frame (variable) | Fixed step | Default fixed rate |
|---|---|---|---|
| Unity | Update, LateUpdate — Time.deltaTime | FixedUpdate — Time.fixedDeltaTime | 0.02 s (50 Hz) |
| Godot | _process(delta) | _physics_process(delta) | 60 ticks/s (physics/common/physics_ticks_per_second) |
| Unreal | Tick(DeltaSeconds) | physics substepping / async physics tick | project physics settings |
| Bevy | Update — Res<Time> | FixedUpdate — Res<Time> is Time<Fixed> there | 64 Hz |
| Phaser | update(time, delta) (ms) | Arcade physics' own step (fps, fixedStep) | 60 |
| PixiJS 8 | ticker.add(t => …) — t.deltaMS | your accumulator | — |
| three.js / Babylon.js | setAnimationLoop + THREE.Timer / engine.getDeltaTime() (ms) | your accumulator, or the physics plugin's | — |
| MonoGame | Update(GameTime) | IsFixedTimeStep = true (default) | 1/60 s |
| pygame | dt = clock.tick(60) / 1000 | your accumulator | — |
Use the engine's fixed callback for physics and authoritative rules. Write your own loop only where the engine has none (web renderers, pygame, custom servers).
const STEP = 1 / 60;
const MAX_FRAME = 0.25; // clamp: a 3 s tab-switch must not run 180 steps
let acc = 0;
let last = performance.now();
function frame(now: number) {
const frameTime = Math.min((now - last) / 1000, MAX_FRAME);
last = now;
acc += frameTime;
while (acc >= STEP) {
previous.copyFrom(current); // keep the last state for interpolation
simulate(current, STEP); // rules + physics, fixed dt only
acc -= STEP;
}
render(interpolate(previous, current, acc / STEP));
requestAnimationFrame(frame);
}
requestAnimationFrame(frame);
Rigidbody.interpolation = Interpolate, Godot physics/common/physics_interpolation (2D since 4.3, 3D since 4.4), Bevy interpolation crates or a manual Time<Fixed>::overstep_fraction() blend.// ❌ frame-rate dependent: twice as fast at 120 FPS, crawls at 30
transform.position += velocity;
camera.position = Vector3.Lerp(camera.position, target, 0.1f);
// ✅ delta-scaled; exponential smoothing that reads the same at any frame rate
transform.position += velocity * Time.deltaTime;
float t = 1f - Mathf.Exp(-sharpness * Time.deltaTime);
camera.position = Vector3.Lerp(camera.position, target, t);
# ❌ counts frames: a 1 s cooldown is 0.42 s at 144 FPS
var frames_left := 60
func _process(_delta: float) -> void:
frames_left -= 1
# ✅ counts seconds
var cooldown_left := 1.0
func _process(delta: float) -> void:
cooldown_left = maxf(0.0, cooldown_left - delta)
Acceleration needs care too: velocity += accel * dt; position += velocity * dt (semi-implicit Euler) is stable at a fixed step and drifts at a variable one — another reason to simulate on the fixed clock.
Time.timeScale with UI on Time.unscaledDeltaTime; Godot Engine.time_scale with pause menus on process_mode = PROCESS_MODE_ALWAYS; Bevy Time<Virtual> (pausable, scalable) vs Time<Real>; Unreal SetGlobalTimeDilation with UI ticking while paused.timeScale = 0 stops FixedUpdate in Unity — anything that must run while paused (menus, input polling for "unpause") cannot live there.visibilitychange on the web, OnApplicationPause, NOTIFICATION_APPLICATION_FOCUS_OUT), and clamp the first delta after resuming.Replays, lockstep RTS and rollback netcode need the same inputs to produce the same state on every machine:
dt reaches the simulation.IndexMap, or arrays); no wall-clock reads inside a step.it("covers the same distance at 30 and 60 steps per second", () => {
const a = new Mover({ speed: 5 }); for (let i = 0; i < 60; i++) a.step(1 / 60);
const b = new Mover({ speed: 5 }); for (let i = 0; i < 30; i++) b.step(1 / 30);
expect(a.x).toBeCloseTo(5, 5);
expect(b.x).toBeCloseTo(a.x, 5);
});
Inject dt; never sleep in a test. Engine tests advance frames explicitly (yield return new WaitForFixedUpdate(), runner.simulate_frames(n), app.update() with a manual time strategy).
Update/_process — it fights the physics step and tunnels.FixedUpdate: a key pressed between two steps is missed. Read in the frame callback, consume in the fixed one.deltaMS, Babylon getDeltaTime()).ticker.deltaTime is a frame-scaled factor (≈1 at 60 FPS), not seconds.frameCount, % 60 or a frame counter used as a timer.Time.time / performance.now() inside a rule class.还没有评价。欢迎分享你的使用感受。
无需登录即可发表。欢迎分享使用感受、提问,或说明在哪些环境下无法运行。
还没有评论。来写第一条吧。
Use when writing acceptance criteria for a task - express each as an observable Given/When/Then that QA can execute, including negative cases
中文简介正在准备中。当前显示原文说明。
Use when the diff adds or changes an endpoint, resolver, RPC, job or query that takes an object id, a role check, a request binding or a tenant filter - BOLA/IDOR, function-level authorization, mass assignment and tenant scoping
中文简介正在准备中。当前显示原文说明。
Use on every UI change - semantic HTML, labels for controls, keyboard-navigable dialogs/menus, visible focus, and never color as the only signal
中文简介正在准备中。当前显示原文说明。
Use when a task changes any screen, form, dialog, menu or control - Lighthouse/axe scan of the changed screens, a keyboard walk, and the thresholds that fail a task
中文简介正在准备中。当前显示原文说明。
How to work a task returned with review, QA or UAT findings. Use when a task is in need_revision or PR review comments are in your context.
中文简介正在准备中。当前显示原文说明。
Use when the repository keeps its alerting in code, or a person asks for alerts outside TaskTrooper - PrometheusRule YAML, a Cloud Monitoring alert policy in Terraform, a Datadog monitor, each routed to TaskTrooper's alert ingest URL so it opens an incident here
中文简介正在准备中。当前显示原文说明。