Use the Input
class to check if any key or button of an input action is pressed:if Input.is_action_pressed("move_right"):
velocity.x = speed
For actions that should trigger once, use Input.is_action_just_pressed()
, and for released actions, use Input.is_action_released()
. They return true
only on the frame in which the action changes state.if Input.is_action_just_pressed("jump"):
velocity.y = -jump_strength
Use the InputMap
singleton to create and modify input actions in code:
- Add an action name to the input map.
- Create an
InputEvent
object representing the input.
- Assign the input event to the action.
InputMap.add_action("shoot")
var event_space := InputEventKey.new()
event_space.physical_keycode = KEY_SPACE
InputMap.action_add_event("shoot", event_space)
This is useful for plugins, among other things. You can insert input actions required by your plugin when users install it and remove them when the plugin is disabled.To erase an input action, use InputMap.erase_action()
:InputMap.erase_action("shoot")
This is useful for cleaning up input actions registered in a plugin.You can modify input actions in code by adding or removing input events. The following example erases all events for the "shoot" action and adds a new event:InputMap.action_erase_events("shoot")
var click_event := InputEventMouseButton.new()
click_event.button_index = MOUSE_BUTTON_LEFT
InputMap.action_add_event("shoot", click_event)
This is great for letting the player remap inputs and for offering multiple input schemes.Override the _input()
, _unhandled_input()
, or similar virtual input methods in scripts to receive and handle input events individually. For example, to toggle fullscreen when pressing f11:func _input(event: InputEvent) -> void:
if event is InputEventKey:
if event.scancode == KEY_F11 and event.pressed:
toggle_fullscreen()
To consume an input event and prevent it from propagating to other nodes, call Viewport.set_input_as_handled()
:func _input(event: InputEvent) -> void:
if event.is_action_pressed("cancel"):
close_menu()
get_viewport().set_input_as_handled()
You can use input actions in virtual input methods like _unhandled_input()
:func _input(event: InputEvent) -> void:
if event.is_action_pressed("quick_save"):
SaveGame.quick_save()
For gameplay inputs, when using the InputEvent
system, favor using _unhandled_input()
. This method is called after _input()
and _gui_input()
, so it ensures gameplay actions don't happen behind an open menu or dialog, for example.func _unhandled_input(event: InputEvent) -> void:
if event.is_action_pressed("cancel"):
cancel_interaction()
Some Control
nodes like Button
or ColorRect
automatically consume mouse input events by default. This ensures that clicking a piece of the user interface does not also interact with the game world behind it.You can change this behavior using the mouse_filter
property to let clicks pass through to nodes behind them:extends ColorRect
func _ready() -> void:
mouse_filter = Control.MOUSE_FILTER_IGNORE
In Control
nodes, override _gui_input()
to detect and handle UI-specific input events. The function reports input events like mouse clicks within the node's bounding box and key presses while the node has keyboard focus.A good example of where you'd use _gui_input()
is a grid-based inventory system where you drag items around and stack them:extends Panel
var held_item: Item = null
func _gui_input(event: InputEvent) -> void:
if event.is_action_pressed("mouse_left"):
if held_item != null:
place_held_item()
else:
pick_up_item()
You can connect the gui_input
signal of a Control
node to a method in the node's script or, better, to a method in a separate script. All input events detected by the Control
node are sent to the connected method. This allows grouping input handling for multiple Control
nodes in a single script.Here's an example with a menu that contains multiple generated buttons. We want the selected buttons to cycle. Pressing down when the last button is selected should select the first button and vice-versa. We connect the gui_input
signal of each button to a method in the menu script:extends Panel
var _selected_item_index := 0
var _item_count := 3
func _ready() -> void:
for index: int in _item_count:
var button := Button.new()
button.text = "Item " + str(index)
add_child(button)
button.gui_input.connect(_on_button_input)
func _on_button_input(event: InputEvent) -> void:
if event.is_action_pressed("cancel"):
button.release_focus()
_selected_item_index = -1
return
var direction := 0
elif event.is_action_pressed("ui_up"):
direction = -1
elif event.is_action_pressed("ui_down"):
direction = 1
_selected_item_index = wrapi(_selected_item_index + direction, 0, _item_count - 1)
get_child(_selected_item_index).grab_focus()
You can generate input events programmatically by calling Input.parse_input_event()
and passing an InputEvent
object. This is useful for simulating input events or for creating custom input events.This example simulates pressing space:var event := InputEventKey.new()
event.scancode = KEY_SPACE
event.pressed = true
Input.parse_input_event(event)
You can also use this to create custom input events for your game or application, like custom touch gestures.You can move the mouse cursor programmatically by calling Viewport.warp_mouse()
, Input.warp_mouse()
, or Control.warp_mouse()
. You can use these methods for mechanics, like wrapping the mouse cursor around the screen.This example warps the mouse cursor to the center of the game window (or the screen if the game is fullscreen):func _ready() -> void:
get_viewport().warp_mouse(get_viewport().get_visible_rect().size / 2)