Quick answer: The most common cause is that the action name in your code does not match the action name in the Input Map. Action names are case-sensitive and must match exactly. Also check that the action has at least one input event (key, button, etc.) assigned to it in Project Settings > Input Map.
Here is how to fix Godot input action not detected. You press the key, nothing happens. Input.is_action_pressed("jump") returns false no matter how hard you mash the spacebar. Your Input Map looks correct, the action is defined, the key is bound — but your game ignores the input entirely. This is the kind of bug that can waste an hour of debugging. Let us pinpoint the exact cause.
The Symptom
Your script checks for an input action using Input.is_action_pressed(), Input.is_action_just_pressed(), or through the _input() / _unhandled_input() callbacks. The function always returns false or the callback is never triggered, despite the correct key being pressed. No error messages appear in the output.
This problem is silent and gives you zero feedback about what is wrong. Unlike a missing node or a type error, Godot does not warn you when you query a nonexistent input action. It simply returns false, which makes the bug look like a logic error rather than a configuration error.
A variant of this symptom is the input working in some scenes but not others, or working when the game starts but stopping after a scene change. This points to the input being consumed by a GUI element or the node’s process mode being affected by the scene tree state.
Another common variant is the input registering once on the first press but then never again. This usually means is_action_just_pressed is being called in a context where it fires correctly but some other logic prevents the action from completing, and the developer misattributes the problem to the input system.
Input Map Configuration
The first thing to check is the Input Map itself. Go to Project > Project Settings > Input Map. Make sure the “Show Built-in Actions” toggle is on if you cannot find your action — Godot has many built-in actions that are hidden by default.
Verify three things about your action:
1. The action name matches your code exactly. Action names are case-sensitive. If the Input Map has Jump but your code checks for "jump", it will not match. Likewise, "move_left" is different from "move left" or "moveLeft". Copy the action name from the Input Map and paste it into your code to avoid any possibility of a typo.
2. The action has at least one input event. Creating an action name without binding any keys, buttons, or axes to it means the action exists but can never be triggered. Click the “+” button next to the action and assign a key or controller button.
3. The dead zone is appropriate. For analog stick actions, the dead zone defaults to 0.5 (50%). If the player’s stick does not reach past this threshold, the action will not trigger. Reduce the dead zone for more sensitive detection or increase it to filter out stick drift.
# Diagnostic: verify an action exists and check its state
func _physics_process(delta):
if InputMap.has_action("jump"):
print("jump action exists, pressed: ", Input.is_action_pressed("jump"))
else:
push_error("Action 'jump' does not exist in Input Map!")
The InputMap.has_action() method is your best diagnostic tool. If it returns false, the action simply does not exist, and you know the problem is in the Input Map, not your code. Add this check early in development for every action your game uses.
Choosing the Right Input Callback
Godot provides multiple ways to read input, and using the wrong one for your use case is a frequent source of confusion. Here is when to use each approach:
extends CharacterBody2D
# APPROACH 1: Poll in _physics_process (best for continuous movement)
func _physics_process(delta):
var direction = Input.get_axis("move_left", "move_right")
velocity.x = direction * SPEED
move_and_slide()
# APPROACH 2: Event callback (best for one-shot actions)
func _unhandled_input(event):
if event.is_action_pressed("jump") and is_on_floor():
velocity.y = JUMP_VELOCITY
# APPROACH 3: _input (receives events before GUI)
func _input(event):
if event.is_action_pressed("pause"):
get_tree().paused = !get_tree().paused
_input vs _unhandled_input: The _input callback receives every input event before the GUI processes it. _unhandled_input only receives events that no GUI node consumed. If you have a Button or TextEdit focused and use _unhandled_input for gameplay, key presses that the GUI handles will not reach your callback. This is usually desirable for gameplay — you do not want the player to jump while typing in a chat box.
However, if your entire screen is covered by a Control node (like a ColorRect background or a full-screen UI container), it may be consuming all input events before they reach _unhandled_input. Set the Control’s Mouse > Filter property to Ignore on any UI elements that should not block input.
Polling vs events: Input.is_action_pressed() checks the current state of the action at the moment you call it. It is ideal for continuous checks in _process or _physics_process. The event callbacks give you discrete press and release events, which are better for actions that should happen exactly once per press (like jumping, shooting, or opening a menu).
A subtle issue arises when you use Input.is_action_just_pressed() in _process(). Because _process can run at variable frame rates and may execute multiple times between physics ticks, the “just pressed” state can be true for multiple frames. If your jump logic is in _process, you might get double jumps. Move one-shot action checks to _physics_process or use _unhandled_input instead.
Actions Not Working After Scene Changes
If input works in your test scene but stops working after transitioning to another scene, there are several possible causes:
Process mode set incorrectly. If your game pauses the scene tree during transitions (e.g., for a loading screen), nodes with the default process mode will stop processing, including their _input and _unhandled_input callbacks. Set the node’s process_mode to PROCESS_MODE_ALWAYS if it needs to receive input during pauses.
# Ensure this node always receives input, even when paused
func _ready():
process_mode = Node.PROCESS_MODE_ALWAYS
Node not in the scene tree. After a scene change, the previous scene’s nodes are freed. If your input handler was on a node in the old scene, it no longer exists. Use Autoloads (singletons) for input handlers that need to persist across scene changes, or attach the handler to a node in the new scene.
Input consumed by a transition overlay. If you use a CanvasLayer for screen transitions (fade to black, etc.), and it contains a Control node that is set to receive mouse events, it may consume all input events. Make sure your transition overlay’s Control nodes have mouse_filter = MOUSE_FILTER_IGNORE after the transition completes.
Action bindings modified at runtime. If your game allows key rebinding and stores the bindings in a save file, make sure the bindings are reloaded after a scene change. If the Input Map is reset to defaults during a transition, custom bindings will be lost.
Dead Zones and Analog Input
For controller and gamepad input, dead zones are a critical but often overlooked setting. The dead zone determines how far an analog stick must be pushed before the action registers.
# Check raw axis value to debug dead zone issues
func _physics_process(delta):
var raw_x = Input.get_joy_axis(0, JOY_AXIS_LEFT_X)
var action_x = Input.get_axis("move_left", "move_right")
print("Raw axis: ", raw_x, " Action value: ", action_x)
# If raw_x shows a value but action_x is 0,
# the dead zone is filtering out the input
The default dead zone of 0.5 means the stick must be pushed past the halfway point to register. For precise games or players with controllers that have limited stick range, this can feel unresponsive. You can adjust dead zones per action in the Input Map, or set them globally with Input.set_joy_axis_deadzone().
A related issue is axis direction. In the Input Map, when you add a joypad axis event to an action, you must specify the direction (positive or negative). If your action expects a positive axis value but the controller sends a negative value for that direction, the action will not trigger. The left stick left is negative X, right is positive X, up is negative Y, and down is positive Y.
"If your input action does not work, print InputMap.has_action with your action string. If it returns false, the problem is a typo. If it returns true, the problem is your callback choice or the dead zone."
Related Issues
If your input actions work but is_action_just_pressed fires multiple times per press, see our dedicated guide on just_pressed registering multiple times. For issues specific to gamepad and controller detection, check gamepad input not detected. If your inputs stop working after scene changes specifically, input actions after scene changes covers the persistence and process mode issues in depth.