Input Handling
Handle keyboard, mouse, gamepad, and touch input with proper buffering and accessibility support.
MANDATORY script triggers (by scenario)
| Scenario |
Load before coding |
| Jump/dash/coyote feel |
[inputbuffer.gd](scripts/inputbuffer.gd) (physics-tied decay) + [advancedinputbuffer.gd](scripts/advancedinputbuffer.gd) for multi-action priority |
| Settings remapping UI |
[saferuntimerebind.gd](scripts/saferuntimerebind.gd) (ConfigFile persist to user://) |
| Analog stick movement |
[analogdeadzonemanager.gd](scripts/analogdeadzonemanager.gd) — never raw axis without radial deadzone |
| "Press X / Press E" prompts |
[glyphpromptmanager.gd](scripts/glyphpromptmanager.gd) |
| UI nav vs gameplay confirm |
[inputechofilter.gd](scripts/inputechofilter.gd) — echoes move menus, not Confirm/Back |
| Gameplay vs menu clicks |
[unhandledinputpriority.gd](scripts/unhandledinputpriority.gd) |
Do-NOT-Load (by scenario)
| Scenario |
Load |
Do NOT load |
| Settings remapping UI |
saferuntimerebind.gd |
multitouchgestures.gd, mousecapturemanager.gd, combo/replay injectors |
| Mobile / touch gestures |
multitouchgestures.gd |
mousecapturemanager.gd, desktop remapper persistence |
| Jump/dash buffer only |
inputbuffer.gd / advancedinput_buffer.gd |
Remapper, multi-touch, replay, combo validator |
| FPS mouse look |
mousecapturemanager.gd + deadzone/glyph as needed |
multitouchgestures.gd, combo/replay |
| Combo / fighting sequences |
combo_validator.gd + buffers |
Touch gestures, mouse capture |
| Replay / virtual injection tests |
inputreplaybuffer.gd / virtualinputinjector.gd |
Remapper UI, multi-touch |
Available Scripts
[advancedinputbuffer.gd](scripts/advancedinputbuffer.gd)
Frame-perfect input buffering system for responsive jumps, dashes, and combo chains.
[inputbuffer.gd](scripts/inputbuffer.gd)
Timed action buffer with physicsprocess decay so windows match CharacterBody consumption, not render FPS.
[saferuntimerebind.gd](scripts/saferuntimerebind.gd)
Dynamic input rebinding with conflict detection and user://input_rebinds.cfg persistence.
[analogdeadzonemanager.gd](scripts/analogdeadzonemanager.gd)
Radial deadzone management for analog sticks to eliminate drift while maintaining natural follow-through.
[multitouchgestures.gd](scripts/multitouchgestures.gd)
Handling touch, drags, and pinch-to-zoom gestures for mobile and touchscreen compatibility.
[inputechofilter.gd](scripts/inputechofilter.gd)
Filtering echo events to distinguish between hold-to-navigate (UI) and one-time gameplay actions.
[mousecapturemanager.gd](scripts/mousecapturemanager.gd)
Robust mouse capture and sensitivity scaling logic for FPS and mouse-intensive systems.
[holdtoggleaccessibility.gd](scripts/holdtoggleaccessibility.gd)
Software-side support for user-defined 'Hold' vs 'Toggle' accessibility preferences.
[glyphpromptmanager.gd](scripts/glyphpromptmanager.gd)
Real-time switching between Keyboard and Gamepad UI prompts based on the last active device.
[actionstatemachine.gd](scripts/actionstatemachine.gd)
Tracking the lifecycle of an action ('Just Pressed', 'Held', 'Released') for complex state logic.
[unhandledinputpriority.gd](scripts/unhandledinputpriority.gd)
Demonstrating the correct use of unhandledinput to prevent gameplay logic from leaking into UI.
[virtualinputinjector.gd](scripts/virtualinputinjector.gd)
Input.parseinputevent injection for CI tutorials / AI assistance — not physical hardware.
[combovalidator.gd](scripts/combovalidator.gd)
Rolling timed sequence buffer for special-move validation (fighting / action RPG).
[inputreplaybuffer.gd](scripts/inputreplaybuffer.gd)
Frame-tagged capture + deterministic replay via parseinputevent.
NEVER Do in Input Handling
- NEVER poll input in
process() for gameplay actions — Use physicsprocess() or unhandledinput(). process() is frame-rate dependent, causing dropped inputs at low FPS [22].
- NEVER use hardcoded key checks (e.g.,
KEY_W) — Always use InputMap actions. Hardcoded keys prevent rebinding and break compatibility with non-QWERTY layouts [23].
- NEVER ignore analog stick deadzones — Drifting sticks at 0.05 magnitude will cause unintended movement. Implement a radial deadzone (not axial) in code or settings [24].
- NEVER assume a single input device — Players may switch between Keyboard and Controller mid-session. Use
Input.joyconnectionchanged to update UI prompts dynamically [25].
- NEVER use
input() for gameplay actions — input() fires for ALL events (including UI). Use unhandledinput() so gameplay logic doesn't trigger while clicking menus [26].
- NEVER omit input buffering in fast-paced games — If a player presses jump 50ms before landing, the input is lost without a buffer. Implement a 100-150ms buffer for a "tight" feel [27].
- NEVER use
Input.isactionpressed() for one-time triggers — It returns true every frame the key is held. Use justpressed for jumps, attacks, and toggles to avoid logic spam.
- NEVER implement manual 'Hold vs Toggle' logic in multiple places — Centralize it in a setting or input wrapper to ensure accessibility consistency across the whole game.
- NEVER forget to handle
InputEvent.is_echo() in UI navigation — Echo events (keyboard repeat) should move menus but rarely should they trigger "Confirm" or "Back" actions.
- NEVER capture the mouse without a 'Release' shortcut — If your game crashes or blocks
ui_cancel, the user is trapped. Always provide a fallback escape for mouse capture.
Input Propagation & Isolation
Godot propagates input events in a specific order. Understanding this is key to isolating UI from gameplay.
_input(event): High-priority global intercept. Use for dev consoles or debug overlays.
guiinput(event): Handled by Control nodes (UI). If a UI element consumes the event (e.g., clicking a button), it calls accept_event(), stopping further propagation.
unhandledinput(event): Reached ONLY if no UI element consumed the event. Expert Pattern: Put all gameplay logic (jump, shoot) here to prevent accidental triggers while interacting with menus.
InputMap Best Practices
Avoid physical key checks. Define semantic actions (e.g., move_left, interact) in Project Settings > Input Map.
1. Analog Deadzones
Analog sticks suffer from drift. MANDATORY: [analogdeadzonemanager.gd](scripts/analogdeadzonemanager.gd). Prefer Input.get_vector() for circular deadzones — never subtract axes into a square deadzone.
2. Expert polling delta (no hardcoded keys)
Gameplay samples actions in physicsprocess / unhandledinput — never KEY / MOUSEBUTTON branches. Pause/cancel must be InputMap actions (e.g. uicancel) so rebinds and non-QWERTY layouts work. See [unhandledinputpriority.gd](scripts/unhandledinputpriority.gd).
Multi-Modal Input & UI Glyphs
Modern games must handle simultaneous Controller and Keyboard/Mouse input smoothly.
1. Handling Input Modes
- Mouse Aiming: Process
InputEventMouseMotion in unhandledinput() for relative movement ([mousecapturemanager.gd](scripts/mousecapturemanager.gd)).
- Stick Movement: Poll vectors in
physicsprocess() after [analogdeadzonemanager.gd](scripts/analogdeadzonemanager.gd).
2. Dynamic Glyph Swapping
MANDATORY: [glyphpromptmanager.gd](scripts/glyphpromptmanager.gd) for last-device prompt swaps. Do not hand-roll event is InputEventJoypadButton detectors in every HUD widget.
Expert Input Extensions (script sole-source)
- Input buffering — MANDATORY: [inputbuffer.gd](scripts/inputbuffer.gd) + [advancedinputbuffer.gd](scripts/advancedinputbuffer.gd). Do not paste jump-timer tutorials inline.
- Coyote time — Owned by movement skills: godot-characterbody-2d (
frameperfectcoyote_time.gd) and godot-genre-platformer. Pair with buffers from this skill; do not re-implement coyote here.
- Multiplayer input sync — Do not RPC
syncinput here. Route to godot-multiplayer-networking for authoritative action snapshots / getremotesenderid validation.
- Virtual injection — MANDATORY: [virtualinputinjector.gd](scripts/virtualinputinjector.gd) (
Input.parseinputevent).
- Combo sequences — MANDATORY: [combovalidator.gd](scripts/combovalidator.gd); fighting fiction stays in
godot-genre-fighting.
- Deterministic replay — MANDATORY: [inputreplaybuffer.gd](scripts/inputreplaybuffer.gd).
Deep recipes (on demand)
| Topic |
Reference / script |
| Buffering / coyote / MP sync |
[input-event-processing.md](references/input-event-processing.md) |
| Virtual injection / combos / replay |
[expert-input-extensions.md](references/expert-input-extensions.md) |
| InputMap & device IDs |
[inputmap-best-practices.md](references/inputmap-best-practices.md) |
Reference
Progressive disclosure: open Official Documentation links only when researching a specific API; load Related Skills when routing to a peer domain — do not preload the whole lattice.
Official Documentation
- Using InputEvent — Event propagation order (
input → GUI → unhandled_input) and why gameplay belongs after UI consumes events.
- Input examples — Practical
InputMap action polling, mouse buttons, and keyboard patterns this skill builds on.
- Controllers, gamepads, and joysticks — Joypad connection, button/axis events, and multi-device mapping for remappers and glyph swaps.
- Controller vibration and features — Extended pad capabilities beyond basic buttons when shipping console-style feedback.
- Mouse and input coordinates — Viewport vs screen coordinates for clicks, aim, and capture-relative motion.
- Customizing the mouse cursor — Cursor shapes alongside
Input.mouse_mode capture/release flows.
- Handling quit requests — Safe ESC / back / quit paths so mouse capture never traps the player.
- Input — Singleton API:
isaction*, getvector, mousemode, parseinput_event, and joy connection signals.
- InputMap — Runtime
actionadd_event / erase / conflict checks for safe rebinding.
- InputEvent — Base event API including
isecho(), isactionpressed(), and device IDs.
- Idle and Physics Processing — Why hold/poll gameplay input in
physicsprocess, not frame-tied process.
- Control —
guiinput / acceptevent so menus stop events before unhandledinput gameplay.
Related Skills
Prerequisites
- godot-project-foundations — Project Settings Input Map, scene boot, and Autoload registration that host remappers and glyph managers.
- godot-gdscript-mastery — Typed
InputEvent branches, StringName actions, and safe signal/await patterns used in buffers and device routers.
Complements
Downstream / consumers
Master
- godot-master — Library router and mirrored module entry; open when discovering which Domain Skill owns a cross-cutting input concern.