-
-
Notifications
You must be signed in to change notification settings - Fork 3.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add a page about gamepad/controller support in Godot #4620
Merged
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,246 @@ | ||
.. _doc_controllers_gamepads_joysticks: | ||
|
||
Controllers, gamepads, and joysticks | ||
==================================== | ||
|
||
Godot supports hundreds of controller models thanks to the community-sourced | ||
`SDL game controller database <https://github.com/gabomdq/SDL_GameControllerDB>`__. | ||
|
||
Controllers are supported on Windows, macOS, Linux, Android, iOS, and HTML5. | ||
|
||
Note that more specialized devices such as steering wheels, rudder pedals and | ||
`HOTAS <https://en.wikipedia.org/wiki/HOTAS>`__ are less tested and may not | ||
always work as expected. If you have access to one of those devices, don't hesitate to | ||
`report bugs on GitHub <https://github.com/godotengine/godot/blob/master/CONTRIBUTING.md#reporting-bugs>`__. | ||
|
||
In this guide, you will learn: | ||
|
||
- **How to write your input logic to support both keyboard and controller inputs.** | ||
- **How controllers can behave differently from keyboard/mouse input.** | ||
- **Troubleshooting issues with controllers in Godot.** | ||
|
||
Supporting universal input | ||
-------------------------- | ||
|
||
Thanks to Godot's input action system, Godot makes it possible to support both | ||
keyboard and controller input without having to write separate code paths. | ||
Instead of hardcoding keys or controller buttons in your scripts, you should | ||
create *input actions* in the Project Settings which will then refer to | ||
specified key and controller inputs. | ||
|
||
Input actions are explained in detail on the :ref:`doc_inputevent` page. | ||
|
||
.. note:: | ||
|
||
Unlike keyboard input, supporting both mouse and controller input for an | ||
action (such as looking around in a first-person game) will require | ||
different code paths since these have to be handled separately. | ||
|
||
Which Input singleton method should I use? | ||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||
|
||
In Godot 4.0, there are 3 ways to get input in an analog-aware way: | ||
|
||
- When you have two axes (such as joystick or WASD movement) and want both | ||
axes to behave as a single input, use ``Input.get_vector()``: | ||
|
||
.. tabs:: | ||
.. code-tab:: gdscript GDScript | ||
|
||
# `velocity` will be a Vector2 between `Vector2(-1.0, -1.0)` and `Vector2(1.0, 1.0)`. | ||
var velocity = Input.get_vector("move_left", "move_right", "move_forward", "move_back") | ||
|
||
# The line above is a shorter form of: | ||
var velocity = Vector2(Input.get_action_strength("move_right") - Input.get_action_strength("move_left"), | ||
Input.get_action_strength("move_back") - Input.get_action_strength("move_forward")).clamped(1) | ||
|
||
.. code-tab:: csharp | ||
|
||
// `velocity` will be a Vector2 between `Vector2(-1.0, -1.0)` and `Vector2(1.0, 1.0)`. | ||
Vector2 velocity = Input.GetVector("move_left", "move_right", "move_forward", "move_back"); | ||
|
||
// The line above is a shorter form of: | ||
Vector2 velocity = new Vector2(Input.GetActionStrength("move_right") - Input.GetActionStrength("move_left"), | ||
Input.GetActionStrength("move_back") - Input.GetActionStrength("move_forward")).Clamped(1); | ||
|
||
- When you have one axis that can go both ways (such as a throttle on a | ||
flight stick), or when you want to handle separate axes individually, | ||
use ``Input.get_axis()``: | ||
|
||
.. tabs:: | ||
.. code-tab:: gdscript GDScript | ||
|
||
# `walk` will be a floating-point number between `-1.0` and `1.0`. | ||
var walk = Input.get_axis("move_left", "move_right") | ||
|
||
# The line above is a shorter form of: | ||
var walk = Input.get_action_strength("move_right") - Input.get_action_strength("move_left") | ||
|
||
.. code-tab:: csharp | ||
|
||
// `walk` will be a floating-point number between `-1.0` and `1.0`. | ||
float walk = Input.GetAxis("move_left", "move_right"); | ||
|
||
// The line above is a shorter form of: | ||
float walk = Input.GetActionStrength("move_right") - Input.GetActionStrength("move_left"); | ||
|
||
- For other types of analog input, such as handling a trigger or handling | ||
one direction at a time, use ``Input.get_action_strength()``: | ||
|
||
.. tabs:: | ||
.. code-tab:: gdscript GDScript | ||
|
||
# `strength` will be a floating-point number between `0.0` and `1.0`. | ||
var strength = Input.get_action_strength("accelerate") | ||
|
||
.. code-tab:: csharp | ||
|
||
// `strength` will be a floating-point number between `0.0` and `1.0`. | ||
float strength = Input.GetActionStrength("accelerate"); | ||
|
||
For non-analog digital/boolean input (only "pressed" or "not pressed" values), | ||
such as controller buttons, mouse buttons or keyboard keys, | ||
use ``Input.is_action_pressed()``: | ||
|
||
.. tabs:: | ||
.. code-tab:: gdscript GDScript | ||
|
||
# `jumping` will be a boolean with a value of `true` or `false`. | ||
var jumping = Input.is_action_pressed("jump") | ||
|
||
.. tabs:: | ||
.. code-tab:: csharp | ||
|
||
// `jumping` will be a boolean with a value of `true` or `false`. | ||
bool jumping = Input.IsActionPressed("jump"); | ||
|
||
In Godot versions before 4.0, such as 3.2, ``Input.get_vector()`` and | ||
``Input.get_axis()`` aren't available. Only ``Input.get_action_strength()`` | ||
and ``Input.is_action_pressed()`` are available in Godot 3.2. | ||
|
||
Differences between keyboard/mouse and controller input | ||
------------------------------------------------------- | ||
|
||
If you're used to handling keyboard and mouse input, you may be surprised by how | ||
controllers handle specific situations. | ||
|
||
Dead zone | ||
^^^^^^^^^ | ||
|
||
Unlike keyboards and mice, controllers offer axes with *analog* inputs. The | ||
upside of analog inputs is that they offer additional flexibility for actions. | ||
Unlike digital inputs which can only provide strengths of ``0.0`` and ``1.0``, | ||
an analog input can provide *any* strength between ``0.0`` and ``1.0``. The | ||
downside is that without a deadzone system, an analog axis' strength will never | ||
be equal to ``0.0`` due to how the controller is physically built. Instead, it | ||
will linger at a low value such as ``0.062``. This phenomenon is known as | ||
*drifting* and can be more noticeable on old or faulty controllers. | ||
|
||
Let's take a racing game as a real-world example. Thanks to analog inputs, we | ||
can steer the car slowly in one direction or another. However, without a | ||
deadzone system, the car would slowly steer by itself even if the player isn't | ||
touching the joystick. This is because the directional axis strength won't be | ||
equal to ``0.0`` when we expect it to. Since we don't want our car to steer by | ||
itself in this case, we define a "dead zone" value of ``0.2`` which will ignore | ||
all input whose strength is lower than ``0.2``. An ideal dead zone value is high | ||
enough to ignore the input caused by joystick drifting, but is low enough to not | ||
ignore actual input from the player. | ||
|
||
Godot features a built-in dead zone system to tackle this problem. The default | ||
value is ``0.2``, but you can increase it or decrease it on a per-action basis | ||
in the Project Settings' Input Map tab. | ||
For ``Input.get_vector()``, the deadzone can be specified, or otherwise it | ||
will calculate the average deadzone value from all of the actions in the vector. | ||
|
||
"Echo" events | ||
^^^^^^^^^^^^^ | ||
|
||
Unlike keyboard input, holding down a controller button such as a D-pad | ||
direction will **not** generate repeated input events at fixed intervals (also | ||
known as "echo" events). This is because the operating system never sends "echo" | ||
events for controller input in the first place. | ||
|
||
If you want controller buttons to send echo events, you will have to generate | ||
:ref:`class_InputEvent` objects by code and parse them using | ||
:ref:`Input.parse_input_event() <class_Input_method_parse_input_event>` | ||
at regular intervals. This can be accomplished | ||
with the help of a :ref:`class_Timer` node. | ||
|
||
Troubleshooting | ||
--------------- | ||
|
||
.. seealso:: | ||
|
||
You can view a list of | ||
`known issues with controller support <https://github.com/godotengine/godot/issues?q=is%3Aopen+is%3Aissue+label%3Atopic%3Ainput+gamepad>`__ | ||
on GitHub. | ||
|
||
My controller isn't recognized by Godot. | ||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||
|
||
First, check that your controller is recognized by other applications. You can | ||
use the `Gamepad Tester <https://gamepad-tester.com/>`__ website to confirm that | ||
your controller is recognized. | ||
|
||
My controller has incorrectly mapped buttons or axes. | ||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||
|
||
If buttons are incorrectly mapped, this may be due to an erroneous mapping from | ||
the `SDL game controller database <https://github.com/gabomdq/SDL_GameControllerDB>`__. | ||
You can contribute an updated mapping to be included in the next Godot version | ||
by opening a pull request on the linked repository. | ||
|
||
There are many ways to create mappings. One option is to use the mapping wizard | ||
in the `official Joypads demo <https://godotengine.org/asset-library/asset/140>`__. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Note: This is technically not true just yet, but godotengine/godot-demo-projects#575 was merged, so this sentence will be true the next time I make a release of the demos on the Godot Asset Library. |
||
Once you have a working mapping for your controller, you can test it by defining | ||
the ``SDL_GAMECONTROLLERCONFIG`` environment variable before running Godot: | ||
|
||
.. tabs:: | ||
.. code-tab:: bash Linux/macOS | ||
|
||
export SDL_GAMECONTROLLERCONFIG="your:mapping:here" | ||
./path/to/godot.x86_64 | ||
|
||
.. code-tab:: bat Windows (cmd) | ||
|
||
set SDL_GAMECONTROLLERCONFIG=your:mapping:here | ||
path\to\godot.exe | ||
|
||
.. code-tab:: powershell Windows (powershell) | ||
|
||
$env:SDL_GAMECONTROLLERCONFIG="your:mapping:here" | ||
path\to\godot.exe | ||
|
||
To test mappings on non-desktop platforms or to distribute your project with | ||
additional controller mappings, you can add them by calling | ||
:ref:`Input.add_joy_mapping() <class_Input_method_add_joy_mapping>` | ||
as early as possible in a script's ``_ready()`` function. | ||
|
||
My controller works on a given platform, but not on another platform. | ||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||
|
||
macOS | ||
~~~~~ | ||
|
||
Controllers are currently only supported on x86-based Macs. This means | ||
controllers won't work on Macs featuring ARM processors such as the Apple M1. | ||
|
||
Linux | ||
~~~~~ | ||
|
||
Prior to Godot 3.2.4, official Godot binaries were compiled with udev support | ||
but self-compiled binaries were compiled *without* udev support unless | ||
``udev=yes`` was passed on the SCons command line. This made controller | ||
hotplugging support unavailable in self-compiled binaries. | ||
|
||
HTML5 | ||
~~~~~ | ||
|
||
HTML5 controller support is often less reliable compared to "native" platforms. | ||
The quality of controller support tends to vary wildly across browsers. As a | ||
result, you may have to instruct your players to use a different browser if they | ||
can't get their controller to work. | ||
|
||
Also, note that | ||
`controller support was significantly improved <https://github.com/godotengine/godot/pull/45078>`__ | ||
in Godot 3.2.4 and later. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is false in fact. One of the advantages of the using get_vector over this is the handling of the deadzone.
With this solution the deazone end up square instead of circular.
I'm ok with mentionning that they are similar but it's false to say they are equivalent.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
PR opened: #4651