Guide to the Godot game engine/Input
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:
- Key: Allows you to link any keyboard button.
- Joy Button: Allows you to link a controller button.
- Joy Axis: Allows you to link a controller joy-stick movement.
- 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:
- load_from_globals(): Resets actions to those set in ProjectSettings.
- has_action(action: String): Returns true if the action exists.
- action_erase_events(action: String): Clears the action so there are no associated events.
- 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:
- 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.
- 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.
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:
- alt: Set to true if you must press "Alt" on your keyboard.
- ctrl: Set to true if you must press "Ctrl" on your keyboard (Windows only).
- meta: Set to true if you must press "Meta" on your keyboard (Linux only).
- command: Set to true if you must press "Ctrl" (on Windows) or "Meta" (on Linux) on your keyboard.
- 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)
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 .
|
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.
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!
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.
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 | 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.
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)
- Getting started [ ]
- Making it work
- Making it look good
- Advanced help
- Miscellaneous