From 6f328f83fa202a88670900b137028436c3d55bcb Mon Sep 17 00:00:00 2001 From: Hugo Locurcio Date: Sat, 13 Feb 2021 02:11:07 +0100 Subject: [PATCH] Add a page about gamepad/controller support in Godot (#4620) (cherry picked from commit 53c1af720ec982cc55d4c47376ff9079bfaf80b9) --- .../inputs/controllers_gamepads_joysticks.rst | 246 ++++++++++++++++++ tutorials/inputs/index.rst | 1 + 2 files changed, 247 insertions(+) create mode 100644 tutorials/inputs/controllers_gamepads_joysticks.rst diff --git a/tutorials/inputs/controllers_gamepads_joysticks.rst b/tutorials/inputs/controllers_gamepads_joysticks.rst new file mode 100644 index 000000000..048cbf448 --- /dev/null +++ b/tutorials/inputs/controllers_gamepads_joysticks.rst @@ -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 `__. + +Controllers are supported on Windows, macOS, Linux, Android, iOS, and HTML5. + +Note that more specialized devices such as steering wheels, rudder pedals and +`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 `__. + +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() ` +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 `__ + 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 `__ 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 `__. +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 `__. +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() ` +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.3, 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 `__ +in Godot 3.3 and later. diff --git a/tutorials/inputs/index.rst b/tutorials/inputs/index.rst index 545114055..c9138492a 100644 --- a/tutorials/inputs/index.rst +++ b/tutorials/inputs/index.rst @@ -9,3 +9,4 @@ Inputs input_examples mouse_and_input_coordinates custom_mouse_cursor + controllers_gamepads_joysticks