A common s&box bug, and the one idea that fixes it.

Why it happens
The code counts frames, not seconds.
protected override void OnUpdate(){ WorldPosition += Vector3.Forward * 5f;}
OnUpdate runs once per frame. A faster PC draws more frames, so this line runs more times every second.
The fix
Move per second, not per frame.
s&box tells you how long the last frame took, in seconds. It's called Time.Delta.
distance=speed×Time.Delta
Slow frame, bigger step. Fast frame, smaller step.
The fix in code
Scale the step by Time.Delta.
[Property]public float Speed { get; set; } = 300f; protected override void OnUpdate(){ var step = Speed * Time.Delta; WorldPosition += Vector3.Forward * step;}
Speed now means units per second. [Property] lets you tune it in the editor.
Proof
Every PC moves 300 units a second.
| FPS | Time.Delta | Per frame | Per second |
|---|---|---|---|
| 30 | 0.0333 | 10.00 | 300 |
| 60 | 0.0167 | 5.00 | 300 |
| 144 | 0.0069 | 2.08 | 300 |
Bigger steps on slow PCs, smaller steps on fast ones. Same total every second.
The rule
If it changes over time, use Time.Delta.
- Moving
- += speed × Time.Delta
- Turning
- += turnRate × Time.Delta
- Timers
- -= Time.Delta
Using Unity? Same rule. It's called Time.deltaTime.