Jump to content

Guide to the Godot game engine/Input

100% developed
From Wikibooks, open books for an open world

In every game, you are able to press a button or tap on the screen for something to happen. This is called reacting to input. There are two ways to do it: using input maps and manually.

Input map

[edit | edit source]

Go to your Project Settings at Project -> Project Settings... and click on the Input Map tab. You will get a list of input actions, like "ui_select". These are the default ones, and can be edited, but not removed.

You can - and should - make your own, however. After where it says "Action:", type a name for an action, like "shoot", or "move_forward". Press the "Add" button next to it. This will create your action.

You will notice that you have no input events associated with it. Press the "+" button next to your new action. You will see these options:

  1. Key: Allows you to link any keyboard button.
  2. Joy Button: Allows you to link a controller button.
  3. Joy Axis: Allows you to link a controller joy-stick movement.
  4. Mouse Button: Allows you to link a mouse button.


For touch screen and mouse movement, please see the manual input detection section mentioned below.

There are several ways to detect whether or not they are pressed, and the method you choose depends on what the action is for. The functions below return a boolean, unless otherwise stated, and should be put inside "if" or "while" statements.

Function What it's for
is_action_pressed Actions that can be held down, like moving, or shooting an automatic weapon
is_action_just_pressed Actions that only run the moment the button is pressed, and cannot run again until the action is released.
get_action_strength Movement, and only for joy sticks (for precise control). Returns a float, 1 = full joy tilt or pressed and 0 = no tilt or not pressed.
is_action_just_released Actions that run only when released (Button unpressed, for example)

The above methods are all called on the Input singleton. They all accept a single String argument.

if Input.is_action_just_pressed("shoot"):
  pass # Add shooting code here

The String argument must be the name of an input action defined in the input map.

Manual input detection

[edit | edit source]

Let's say that you want to detect mouse movement or touch screen events, or that the input map won't work because you need input for a tool that you can't guarantee the user of the tool (or yourself) will create the input event.

This is when you need manual input detection. This is like using servers. Manual input detection is a low-level equivalent to the input map that is more complex but gives more power.

The below code moves a 2D sprite when you move your mouse, and ignores all other input.

extends Sprite2D

func _input(event):
  if event is InputEventMouseMotion:
    position += event.relative

The below code creates a simple button. _gui_input() is available only to Control derived nodes and runs if focused and you press a key, you pressed it with the mouse or the mouse moves over it.

extends Control
signal button_up
signal button_down

var pressed = false

func _gui_input(event):
  if event is InputEventMouseButton and event.button_index == BUTTON_LEFT:
    if event.pressed:
      get_tree().set_input_as_handled()
      emit_signal("button_down")
      pressed = true
    elif not event.pressed:
      if pressed:
        emit_signal("button_up")
      pressed = false

The get_tree().set_input_as_handled() makes sure other _gui_input() and _unhandled_input() are not called.

There are many input events. They are as follows:

  • InputEventMouse:
    • InputEventMouseButton: Emitted when you click a mouse button. Read with: button_index (BUTTON_* constants), pressed.
    • InputEventMouseMotion: Emitted when you move the mouse. Read with: relative (how much the mouse moved since the last call to input), position (the mouse's new position relative to the top-left of the game window - or the node in "_gui_input" calls).
  • InputEventKey: Emitted when you press a button on the keyboard. Read with: button_index (KEY_* constants), pressed, echo (if true, the button is being held down).
  • InputEventScreen:
    • InputEventScreenTouch: Emitted when you tap the screen. Read with: position (the position you tapped on the screen), pressed (if false, you are untapping the screen).
    • InputEventScreenDrag: Emitted when you drag on the screen. Read with: position (new position), relative (how much the finger moved since the last input call), fingers.
  • InputEventJoy:
    • InputEventJoyButton: Emitted for controller button presses. Read with: pressed, button_index (JOY_* constants).
    • InputEventJoyMotion: Emitted for moving the joy stick. Read with: position, relative.

See more: The InputEvent tutorial.

Input singleton

[edit | edit source]

So reading input is very fun. However, there are a few more well used methods of input. Try to think about it before you read on. What are they?

There are more things besides when using the input singleton, and this section will explain in-depth on what can be achieved and how.

Motion controls

[edit | edit source]

Motion controls are in many popular games, particularly VR and/or AR games, to look around.

func _process():
  # Assume camera_pivot is a Spatial with a child Camera3D node.
  # The gyroscope only works when exported to Android.
  $camera_pivot.rotation += Input.get_gyroscope()
  # The accelerometer is only available when exported to mobile.
  # This makes you move the camera when you move the device (Not when you rotate it)
  $camera_pivot.rotation += Input.get_accelerometer()

This is only for "rotational" motion detecting.

Vibration

[edit | edit source]

Many popular games include vibration. You can call the below when the player is hit:

Input.vibrate_handheld(100)
Input.start_joy_vibration(0, .5, .4, 1.0)

This will vibrate a controller or mobile device for 1 second.

InputMap singleton

[edit | edit source]

The InputMap allows creating input actions via code. This is good in games where the player can change their controls.

See here for the rundown of InputMap.

The following code creates a shoot action which corresponds to pressing the spacebar.

extends Node

func _ready():
  InputMap.add_action("shoot")
  InputMap.action_add_event("shoot", create_key_action(KEY_SPACE))

func create_key_action(key) -> InputEventKey:
  var input = InputEventKey.new()
  input.pressed = true
  input.scancode = key
  return input

It can be any input event, not just InputEventKey.

See the "faking" input section below for more information on creating InputEvents.

Other useful methods:

  1. load_from_globals(): Resets actions to those set in ProjectSettings.
  2. has_action(action: String): Returns true if the action exists.
  3. action_erase_events(action: String): Clears the action so there are no associated events.
  4. erase_action(action: String): Erases the action.

As always, this does not list them all. Just a few of them.

Audio input

[edit | edit source]

To record audio, you need to do 2 things:

  1. Press "Audio" at the bottom of the screen, and press "New Bus". Rename it "Microphone" and click "Add Effect". Press "Record" in the dropdown menu that appears.
  2. Create a new AudioStreamPlayer node for your scene. Click on the Stream value in the Inspector. Choose New AudioStreamMicrophone from the dropdown menu that appears. Set the "Bus" property to "Microphone". Whenever you want to record audio in-game, just turn the "Playing" value to true.

Reading audio for stuff like voice recognition can be done, but it is not easy, and is outside the scope of this book (and outside the knowledge of the author).

"Faking" input

[edit | edit source]

So, you decided that you want to change the InputMap at runtime? But how do you do that?

Godot has several powerful classes that make input detection easier and faking it possible.

See more: The InputEvent tutorial.

InputEventKey

[edit | edit source]

InputEventKey is for detecting keyboard button presses and releases.

The below code allows you to shoot with the A key:

extends Node

func shoot_with_a():
  var input = InputEventKey.new()
  input.pressed = true
  input.scancode = KEY_A
  InputMap.action_erase_events("shoot")
  InputMap.action_add_event("shoot", input)

The "Input.event_erase_actions" clears all actions for the event specified. In this case, the space-bar will no longer make you shoot.

Any key can be specified, though it may not be obvious how to do so.

Key constants
Constant About
KEY_<letter> Letter keys
KEY_<number> Number keys
KEY_KP_MULTIPLY The keypad * key
KEY_KP_DIVIDE The keypad / key
KEY_KP_SUBTRACT The keypad - key
KEY_KP_ADD The keypad + key
KEY_KP_ENTER The keypad Enter key
KEY_KP_PERIOD The keypad . key
KEY_SPACE The Space key
KEY_ENTER The Enter key
KEY_PLUS The + key
KEY_MINUS The - key
KEY_EQUALS The = key
KEY_QUESTION The ? key
KEY_EXCLAIM The ! key
KEY_QUOTEDBL The " key
KEY_NUMBERSIGN The # key
KEY_DOLLAR The $ key
KEY_PERCENT The % key
KEY_AMPERSAND The & key
KEY_APOSTROPHE The ' key
KEY_PARENLEFT The ( key
KEY_PARENRIGHT The ) key
KEY_AT The @ key
KEY_COLON The : key
KEY_SEMICOLON The ; key
KEY_GREATER The > key
KEY_LESS The < key
KEY_BRACKETLEFT The [ key
KEY_BRACKETRIGHT The ] key
KEY_BACKSLASH The \ key
KEY_ASCIICIRCUM The ^ key
KEY_UNDERSCORE The _ key
KEY_QUOTELEFT The ` key
KEY_BRACELEFT The { key
KEY_BRACERIGHT The } key
KEY_BAR The | key
KEY_ASCIITIDLE The ~ key
KEY_STERLING The £ key
KEY_CENT The ¢ key
KEY_YEN The ¥ key
KEY_COPYRIGHT The © key
KEY_REGISTERED The ® key
KEY_UP The Up arrow key
KEY_DOWN The Down arrow key
KEY_LEFT The Left arrow key
KEY_RIGHT The Right arrow key
KEY_TAB The Tab key
KEY_BACKTAB The Shift + Tab keys pressed together
KEY_ESCAPE The Esc key
KEY_DELETE The Delete key
KEY_INSERT The Insert key
KEY_BACK The Backspace key
KEY_SHIFT The Shift key
KEY_ALT The Alt key
KEY_CONTROL The Ctrl key (Windows only)
KEY_META The Meta key (Linux only)
KEY_F<number 1 to 12> The F1 ect. keys on your keyboard
KEY_COMMA The , key
KEY_PERIOD The . key
KEY_ASTERISK The * key
KEY_SLASH The / key
KEY_HOME The Home key
KEY_PAUSE The Pause key
KEY_PRINT The Print Screen key
KEY_CLEAR The Clear key
KEY_END The End key
KEY_SYSREQ The system request key
KEY_PAGEUP The Page Up key
KEY_PAGEDOWN The Page Down key
KEY_NUMLOCK The Num Lock key
KEY_SCROLLLOCK The Scroll Lock key
KEY_CAPSLOCK The Caps Lock key
KEY_MENU The Context Menu key
KEY_HELP The Help key
KEY_BACK The Media Back key. Not to be confused with the back button on an Android device
KEY_FORWARD The Media Forward key
KEY_STOP The Media Stop key
KEY_MEDIAPLAY The Media Play key

If you want to detect if certain modifiers are also pressed, you have access to these variables:

  1. alt: Set to true if you must press "Alt" on your keyboard.
  2. ctrl: Set to true if you must press "Ctrl" on your keyboard (Windows only).
  3. meta: Set to true if you must press "Meta" on your keyboard (Linux only).
  4. command: Set to true if you must press "Ctrl" (on Windows) or "Meta" (on Linux) on your keyboard.
  5. shift: Set to true if you must press "shift" on your keyboard.

You may set more than one of these to true. This makes you need to press all the modifiers set.

If you want to detect releasing the key instead of pressing it, don't set "pressed" to true. If you are adding it to the InputMap, it will always be pressed if the keys for it are not, but only after they have been released for the first time. So how do you fix this then? Actually, it's quite simple!

Try Input.event_<press/release>("shoot"). It works nicely, but if you need it for calls to _input, you should instead use Input.parse_input_event(event).

InputEventMouse

[edit | edit source]

Detecting mouse input or faking it can be explained in two ways: mouse buttons and mouse motion.

See also: mouse and input coordinates tutorial.

InputEventMouseButton

[edit | edit source]

Clicking your mouse is a common action to read, but not as common to fake. It is the simplest action to read and fake, though, needing only 2 values.

extends Node

func shoot_on_click():
  var input = InputEventMouseButton.new()
  input.pressed = true
  input.button_index = BUTTON_LEFT
  InputMap.action_erase_events("shoot")
  InputMap.action_add_event("shoot",input)
Variables
Variable Use
doubleclick If true, the button was double-clicked.
factor The factor (or delta) of the event as a float. When used for high-precision scroll events, this indicates the scroll amount. Only supported on some platforms. If unsupported on the current platform, it may be 0.
Allowed values for button_index
Constant What it means
BUTTON_LEFT Left click
BUTTON_RIGHT Right click
BUTTON_MIDDLE Scroll button pressed down
BUTTON_WHEEL_UP Scroll wheel up.
BUTTON_WHEEL_DOWN Scroll wheel down.

InputEventMouseMotion

[edit | edit source]

Faking mouse motion can be harder, but sometimes very useful. If you actually want to move the mouse, instead use Input.set_mouse_position(<Vector2>). That will also generate a InputEventMouseMotion event to trigger.

Variables
Variable Use
position The new mouse position, relative to the nodes viewport. If called in _gui_input, it is instead relative to the Control node.
relative The new position relative to the mouse position in the last call.
speed The mouse speed in pixels per second

By default, this event is only emitted once per frame rendered at most. If you need more precise input reporting, consider using Input.set_use_accumulated_input(false) to emit events as often as possible. If you need this to draw freehand lines, consider using Bresenham's line algorithm as well to avoid gaps when you move the mouse quickly.

InputEventScreenDrag

[edit | edit source]

(Only available on mobile devices)

Reading and writing screen dragging is harder than InputEventMouseMotion, simply because you cannot force the user to move their finger via code. Okay, that's a lie. But to do that, you would need a degree in mind control or hypnotising, which is well outside the scope of this book!

Variables
Variable Use
position The new position of the finger relative to the node's viewport. If used in _gui_input, it is relative to the Control node.
relative The finger's new position, relative to its old position.
speed The drag speed in pixels per second.

InputEventScreenTouch

[edit | edit source]

(Only available on mobile devices)

This event is for tapping (or untapping) on the screen.

Variables
Variable Use
position The finger's position relative to the node's viewport. If used in _gui_input, it is relative to the Control.
pressed If true, the user is putting their finger on the screen. Otherwise, they are taking their finger off the screen.

InputEventJoypadButton

[edit | edit source]

This InputEvent is for detecting joy-con buttons (i.e: buttons on a controller, linked to a computer or a console).

Variables
Variables About
button_index The button that is pressed.
If "true", the button is pressed. Otherwise the button is released.

InputEventJoypadMotion

[edit | edit source]

This event is for moving the Joy stick, one axis at a time. This InputEvent can be confusing.

Variables
Variable About
axis A constant that has one of six values: JOY_AXIS_*, where "*" can be:

0: Left stick on the horizontal axis

1: Left stick on the vertical axis

2: Right stick on the horizontal axis

3: Right stick on the vertical axis

6: Left trigger analogue axis

7: Right trigger analogue axis

The other four have no function yet, and are described as "generic game pad axises" and are just used as blank space.

axis_value A number from -1.0 to 1.0.

It is important to know that this InputEvent does not have a Vector2 value you can read from. The following script converts this InputEvent into a Vector3, x and y are for position, z is for the joystick being moved.

func convert_from_joypad_motion(event: InputEventJoypadMotion) -> Vector3:
  match event.axis:
    JOY_AXIS_0:# Left stick horizontal
      return Vector3(event.axis_value, 0, 0)
    JOY_AXIS_1:# Left stich vertical
      return Vector3(0, event.axis_value, 0)
    JOY_AXIS_2:# Right stick horizontal
      return Vector3(event.axis_value, 0, 1)
    JOY_AXIS_3:# Right stick vertical
      return Vector3(0, event.axis_value, 1)
  # An error occurred
  printerr("Invalid axis: %s in call to convert_from_joypad_motion" % [event.axis])
  print_stack() # To help with debugging, print the call stack.
  return Vector3(0, 0, 0)



Guide to the Godot game engine

Getting started [edit]
Installation
What is a node?
Programming
Resources and importing
Signals and methods
Your first game
Making it work
Debugging
Input
Physics
Saving and loading
Multiplayer
Making it look good
UI skinning
Animation
Advanced help
Servers (singletons)
Platform specific
Optimisation
Encryption
Exporting
Plugins
Miscellaneous
Helpful links
Authors and contributors
Print version


<-- previous back to top next -->