Quick answer: Lower per-action Deadzone in the Input Map. For directional input prefer Input.get_axis and Input.get_vector — both handle deadzone and clamping correctly.
A platformer uses Input.get_action_strength("move_right") - Input.get_action_strength("move_left") for horizontal velocity. The player at idle reports tiny non-zero values like 0.03 — analog stick noise getting through. The character creeps slowly even with no input.
Why Strength Leaks Noise
Gamepad sticks have small mechanical play. Even at rest, the OS reports values like 0.01–0.05 instead of exactly 0. Godot’s default deadzone (0.5) drops these to 0 — but if you lowered it for responsive control, you may have dropped it too far.
Two leakage sources:
- Deadzone too low: values below threshold reach
get_action_strength. - Conflicting events: two events bound to the same action with different deadzones produce inconsistent filtering.
The Fix: Tune Deadzone
Project Settings → Input Map. Expand each movement action. Find the Deadzone slider. A practical default is 0.2:
- 0.0: no filtering. Noise leaks.
- 0.2: filters small noise. Good for responsive feel.
- 0.5: default. Filters more aggressively; can feel sluggish on sticks.
Use get_axis for Symmetric Pairs
# Cleaner
var h = Input.get_axis("move_left", "move_right")
Returns -1 if only left is pressed, +1 if only right, 0 if neither or both. Handles deadzone properly. Replaces the subtraction pattern that can produce double-direction values when both are partially active.
get_vector for 2D Movement
var dir = Input.get_vector("move_left", "move_right", "move_up", "move_down")
# dir is already clamped to length ≤ 1
velocity = dir * speed
get_vector returns a Vector2 with the correct deadzone math applied to the combined magnitude (not per-axis). The result is naturally clamped to length 1 — diagonal motion isn’t faster than cardinal motion.
Custom Deadzone in Script
For per-player calibration:
var user_deadzone = 0.15 # from settings
func get_axis_calibrated(neg: String, pos: String) -> float:
var v = Input.get_axis(neg, pos)
return v if abs(v) > user_deadzone else 0.0
Overrides Input Map deadzone with a per-user value. Useful when expose a deadzone slider in settings.
Verifying
Stand at rest with a gamepad connected. print(Input.get_axis("move_left", "move_right")) should return 0 — not 0.02 or 0.05. Push the stick slightly — should snap to non-zero past your deadzone, smoothly increasing toward 1 thereafter.
“Use get_axis and get_vector. The math is built in. Manual subtraction is where deadzone bugs live.”
Always expose a Deadzone setting in your options menu — players with worn sticks compensate; you save your testing time.