| name | godot-input-handling |
| description | Expert patterns for input handling covering InputMap actions, InputEvent processing, controller support, rebinding, deadzones, and input buffering. Use when setting up player controls, implementing input systems, or adding gamepad/accessibility features. Keywords InputMap, InputEvent, gamepad, controller, rebinding, deadzone, input buffer. |
Input Handling
Handle keyboard, mouse, gamepad, and touch input with proper buffering and accessibility support.
Available Scripts
Input buffering for responsive controls - buffers actions for 150ms to ensure tight game feel.
Runtime input rebinding with conflict detection and save/load persistence.
MANDATORY - For Responsive Controls: Read input_buffer.gd before implementing jump/dash mechanics.
NEVER Do in Input Handling
- NEVER poll input in
_process() for gameplay actions — Use _physics_process() or _unhandled_input()_process()` = frame-rate dependent, causes input drops at low FPS.
- NEVER use hardcoded key checks (
KEY_W, KEY_SPACE) — Use InputMap actions. Hardcoded keys = no rebinding, breaks non-QWERTY keyboards.
- NEVER ignore controller deadzones — Stick drift at 0.05 magnitude = character walks alone. ALWAYS implement
Input.get_axis() with 0.15-0.2 deadzone.
- NEVER assume single input device — Player might switch keyboard → gamepad mid-session. Listen to
Input.joy_connection_changed and update UI prompts dynamically.
- NEVER use
//_input() for gameplay actions — _input() fires for ALL events (including UI). Use _unhandled_input() which only fires if UI didn't consume the event.
- NEVER forget input buffering for responsive controls — Player presses jump 50ms before landing? Without buffer, jump is lost. Buffer inputs for 100-150ms for tight game-feel.
InputMap Actions
Setup: Project Settings → Input Map → Add action
# Check if action pressed this frame
if Input.is_action_just_pressed("jump"):
jump()
# Check if action held
if Input.is_action_pressed("fire"):
shoot()
# Check if action released
if Input.is_action_just_released("jump"):
release_jump()
# Get axis (-1 to 1)
var direction := Input.get_axis("move_left", "move_right")
# Get vector
var input_vector := Input.get_vector("left", "right", "up", "down")
InputEvent Processing
func _input(event: InputEvent) -> void:
if event is InputEventKey:
if event.keycode == KEY_ESCAPE and event.pressed:
pause_game()
if event is InputEventMouseButton:
if event.button_index == MOUSE_BUTTON_LEFT and event.pressed:
click_position = event.position
Gamepad Support
# Detect controller connection
func _ready() -> void:
Input.joy_connection_changed.connect(_on_joy_connection_changed)
func _on_joy_connection_changed(device: int, connected: bool) -> void:
if connected:
print("Controller ", device, " connected")
Reference
Related