the symptom, in your words

"Input.Keyboard.Pressed refires on OS key auto-repeat: toggles flip twice"

✓ verified on 26.08.05
lane Writing gameplayposted

▸ SYMPTOM

You bind a toggle to a key with Input.Keyboard.Pressed (open a panel, enable freecam, flip a mode) and it misbehaves on a held press: the panel opens and then closes itself about half a second later. Users report the key "isn't working," so they press longer, which makes it worse.

▸ CAUSE

Input.Keyboard.Pressed fires again on the OS key auto-repeat, not only on the physical down edge. Windows delivers its first repeat at the configured repeat delay (~500 ms by default), so:

snippet
if (Input.Keyboard.Pressed("J")) open = !open;   // toggles TWICE on a held key

toggles once on the real down edge and again on the first auto-repeat: the panel opens, then closes ~0.5 s later. Any one-shot action bound to Pressed re-fires the same way.

▸ FIX

Toggle on the true down edge, tracked with previous-frame state:

snippet
bool down = Input.Keyboard.Down(key);
if (down && !_wasDown) Toggle();   // fires once, on the real press
_wasDown = down;

Down stays true across the whole hold (including between repeats), so a repeat can never re-toggle, at any hold length.

  • Don't reach for a time-based debounce. A "ignore repeats within N ms" window fails on long holds: a later repeat outlives the window and flips state anyway. The previous-frame edge has no such hole.
  • Pressed is fine where re-fire is harmless or wanted: stepping menu rows, paging a list, repeat-fire actions.
  • Audit one-shot raw-letter actions that spend money or mutate state. On a held key they re-fire too; a purchase or a contract mutation bound to Pressed can trigger twice.

Diagnosing a flapping toggle

If a panel or mode flaps and you have no console bridge to inspect it, look at the engine log for paired on/off lines from any consumer that runs on a ~0.5 s heartbeat (a freecam inspect request, a visibility toggle). On/off pairs cycling ~1 s apart with ~0.5 s open windows are the auto-repeat signature.

▸ WHY IT WORKS

Pressed reflects the input event stream, which includes OS repeats: it answers "did a press event arrive this frame," not "did the physical key just go down." Down reflects the physical hold state, which is level, not edged. Deriving your own edge from Down (down && !wasDown) gives you exactly one trigger per physical press regardless of how the OS chooses to repeat the event underneath.

Verified on engine 26.08.05: seen in a real project.
s&box moves fast; an undated fix is a liability. Spot a stale detail?
changelog
  • Published

Want to know when new guides or fixes drop? Join the community to help build this out. Report gotchas, flag outdated fixes, or just lurk.

Join the Discord