Controles, gamepads y joysticks

Godot admite cientos de modelos de controles gracias a la comunidad SDL game controller database.

Los controles son compatibles con Windows, macOS, Linux, Android, iOS y HTML5.

Ten en cuenta que dispositivos más especializados como volantes, pedales de timón y HOTAS (Hands-On Throttle and Stick) son menos probados y es posible que no siempre funcionen como se espera. La capacidad de anular la retroalimentación de fuerza para esos dispositivos aún no está implementada. Si tienes acceso a alguno de esos dispositivos, no dudes en informar errores en GitHub.

En esta guía aprenderás:

  • Cómo escribir su lógica de entrada para admitir entradas de teclado y de controles.

  • Cómo los controles pueden comportarse de manera diferente a la entrada del teclado/mouse.

  • Solución de problemas con los controles en Godot.

Soporte para entrada universal

Gracias al sistema de acción de entrada de Godot, hace posible admitir la entrada tanto del teclado como del control sin tener que escribir rutas de código separadas. En lugar de codificar las teclas o los botones del control en sus scripts, debe crear acciones de entrada en la Configuración del Proyecto, que luego se referirán a las entradas de clave y control especificadas.

Las acciones de entrada se explican en detalle en la página Usando InputEvent.

Nota

A diferencia de la entrada del teclado, admitir la entrada del mouse y del control para una acción (como mirar alrededor en un juego en primera persona) requerirá diferentes rutas de código, ya que deben manejarse por separado.

¿Qué método de entrada singleton debo usar?

Hay 3 formas de obtener entrada de forma analógica:

  • Cuando tenga dos ejes (como un joystick o movimiento WASD) y desee que ambos ejes se comporten como una sola entrada, use Input.get_vector():

 # `velocity` will be a Vector2 between `Vector2(-1.0, -1.0)` and `Vector2(1.0, 1.0)`.
 # This handles deadzone in a correct way for most use cases.
 # The resulting deadzone will have a circular shape as it generally should.
 var velocity = Input.get_vector("move_left", "move_right", "move_forward", "move_back")

 # The line below is similar to `get_vector()`, except that it handles
 # the deadzone in a less optimal way. The resulting deadzone will have
 # a square-ish shape when it should ideally have a circular shape.
 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.0)
  • Cuando tiene un eje que puede ir en ambos sentidos (como un acelerador en una palanca de vuelo), o cuando desea manejar ejes separados individualmente, use Input.get_axis():

# `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")
  • Para otros tipos de entrada analógica, como manejar un disparador o manejar una dirección a la vez, use Input.get_action_strength():

# `strength` will be a floating-point number between `0.0` and `1.0`.
var strength = Input.get_action_strength("accelerate")

Para entradas digitales/booleanas no analógicas (sólo valores "presionados" o "no presionados"), como botones del control, botones del mouse o teclas del teclado, use Input.is_action_pressed():

# `jumping` will be a boolean with a value of `true` or `false`.
var jumping = Input.is_action_pressed("jump")
// `jumping` will be a boolean with a value of `true` or `false`.
bool jumping = Input.IsActionPressed("jump");

En las versiones de Godot anteriores a 3.4, como 3.3, Input.get_vector() y Input.get_axis() no están disponibles. Sólo Input.get_action_strength() y Input.is_action_pressed() están disponibles en Godot 3.3.

Diferencias entre teclado/mouse y entrada del controlador

Si está acostumbrado a manejar la entrada del teclado y el mouse, es posible que se sorprenda de cómo los controles manejan situaciones específicas.

Zona muerta

A diferencia de los teclados y ratones, los controles ofrecen ejes con entradas analógicas. La ventaja de las entradas analógicas es que ofrecen flexibilidad adicional para las acciones. A diferencia de las entradas digitales que sólo pueden proporcionar potencias de 0.0 y 1.0, una entrada analógica puede proporcionar cualquier intensidad entre 0.0 y 1.0. La desventaja es que sin un sistema de zona muerta, la fuerza de un eje analógico nunca será igual a 0.0 debido a cómo está construido físicamente el control. En cambio, permanecerá en un valor bajo como 0.062. Este fenómeno se conoce como drifting y puede ser más notorio en controles viejos o defectuosos.

Tomemos un juego de carreras como ejemplo del mundo real. Gracias a las entradas analógicas, podemos conducir el coche lentamente en una dirección u otra. Sin embargo, sin un sistema de zona muerta, el automóvil se conduciría lentamente por sí mismo incluso si el jugador no está tocando el joystick. Esto se debe a que la fuerza del eje direccional no será igual a 0.0 cuando lo esperamos. Como no queremos que nuestro coche se dirija sólo en este caso, definimos un valor de "zona muerta" de 0.2 que ignorará todas las entradas cuya fuerza sea inferior a 0.2. Un valor de zona muerta ideal es lo suficientemente alto como para ignorar la entrada causada por la deriva del joystick, pero es lo suficientemente bajo como para no ignorar la entrada real del jugador.

Godot cuenta con un sistema de zona muerta incorporado para abordar este problema. El valor predeterminado es 0.2, pero puede aumentarlo o disminuirlo por acción en la pestaña Mapa de entrada de Configuración del proyecto. Para Input.get_vector(), se puede especificar la zona muerta o, de lo contrario, se calculará el valor medio de la zona muerta de todas las acciones del vector.

Eventos de "eco"

A diferencia de la entrada de teclado, mantener presionado un botón del control, como la dirección del D-pad, no generará eventos de entrada repetidos a intervalos fijos (también conocidos como eventos de "eco"). Esto se debe a que, en primer lugar, el sistema operativo nunca envía eventos de "eco" para la entrada del control.

Si desea que los botones del control envíen eventos de eco, tendrá que generar InputEvent objetos por código y analizarlo usando Input.parse_input_event() en intervalos regulares. Esto se puede lograr con la ayuda de un nodo Timer.

Window focus

Unlike keyboard input, controller inputs can be seen by all windows on the operating system, including unfocused windows.

While this is useful for third-party split screen functionality, it can also have adverse effects. Players may accidentally send controller inputs to the running project while interacting with another window.

If you wish to ignore events when the project window isn't focused, you will need to create an autoload called Focus with the following script and use it to check all your inputs:

# Focus.gd
extends Node

var focused := true

func _notification(what: int) -> void:
    match what:
        NOTIFICATION_WM_FOCUS_OUT:
            focused = false
        NOTIFICATION_WM_FOCUS_IN:
            focused = true


func input_is_action_pressed(action: String) -> bool:
    if focused:
        return Input.is_action_pressed(action)

    return false


func event_is_action_pressed(event: InputEvent, action: String) -> bool:
    if focused:
        return Input.is_action_pressed(action)

    return false

Then, instead of using Input.is_action_pressed(action), use Focus.input_is_action_pressed(action) where action is the name of the input action. Also, instead of using event.is_action_pressed(action), use Focus.event_is_action_pressed(event, action) where event is an InputEvent reference and action is the name of the input action.

Power saving prevention

Unlike keyboard and mouse input, controller inputs do not inhibit sleep and power saving measures (such as turning off the screen after a certain amount of time has passed).

To combat this, Godot enables power saving prevention by default when a project is running. If you notice the system is turning off its display when playing with a gamepad, check the value of Display > Window > Energy Saving > Keep Screen On in the Project Settings.

Power saving prevention is not supported on Linux in Godot 3.x, but it is supported in Godot 4.x. As a workaround, increase the screensaver's timeout period to make it less likely to occur during gameplay.

Solución De Problemas

Ver también

Puedes ver una lista de problemas conocidos con el soporte de controladores en GitHub.

Mi control no es reconocido por Godot.

Primero, revisa que tu control es detectado por otras aplicaciones. Puedes usar el sitio web Gamepad Tester para confirmar que tu control es detectado.

Mi control tiene botones o ejes asignados incorrectamente.

Si los botones se asignan incorrectamente, esto puede deberse a una asignación errónea del SDL game controller database. Puede contribuir con un mapeo actualizado para que se incluya en la próxima versión de Godot abriendo un pull request en el repositorio vinculado.

Hay muchas formas de crear asignaciones. Una opción es utilizar el asistente de mapeo en el official Joypads demo. Una vez que tenga un mapeo funcional para su control, puede probarlo definiendo la variable de entorno SDL_GAMECONTROLLERCONFIG antes de ejecutar Godot:

export SDL_GAMECONTROLLERCONFIG="your:mapping:here"
./path/to/godot.x86_64

Para probar asignaciones en plataformas que no son de escritorio o para distribuir su proyecto con asignaciones de controles adicionales, puede agregarlas llamando a : ref: Input.add_joy_mapping() tan pronto como sea posible en la función del script _ready().

Mi control funciona en una plataforma determinada, pero no en otra plataforma.

Linux

Antes de Godot 3.3, los binarios oficiales de Godot se compilaban con soporte de udev, pero los binarios autocompilados se compilaban sin soporte de udev a menos que se pasara udev=yes en la línea de comandos de SCons. Esto hizo que el soporte de hotplugging del control no estuviera disponible en binarios autocompilados.

HTML5

El soporte del control de HTML5 es a menudo menos confiable en comparación con las plataformas "nativas". La calidad de la compatibilidad con el control tiende a variar enormemente entre los navegadores. Como resultado, es posible que deba indicar a sus jugadores que usen un navegador diferente si no pueden hacer que su control funcione.

Además, tenga en cuenta que la compatibilidad con el controlador se mejoró significativamente en Godot 3.3 y versiones posteriores.