Attention: Here be dragons
This is the latest
(unstable) version of this documentation, which may document features
not available in or compatible with released stable versions of Godot.
Checking the stable version of the documentation...
Controles, gamepads e joysticks
Godot supports hundreds of controller models out of the box. Controllers are supported on Windows, macOS, Linux, Android, iOS, and HTML5.
Observe que dispositivos mais especializados, como volantes, pedais de leme e HOTAS são menos testados e nem sempre funcionam como esperado. Substituir o feedback de força para esses dispositivos também não foi implementado ainda. Se você tiver acesso a um desses dispositivos, não hesite em reportar bugs no GitHub.
Neste guia, você aprenderá:
Como escrever sua lógica de entrada para suportar as entradas de teclado e de controles.
Como os controles podem se comportar de maneira diferente da entrada do teclado/mouse.
Solução de problemas com controles no Godot.
Suportando entrada universal
Graças ao sistema de ação de entrada do Godot, o Godot torna possível suportar a entrada do teclado e do controlador sem ter que escrever caminhos de código separados. Em vez de codificar teclas ou botões do controlador em seus scripts, você deve criar ações de entrada nas configurações do projeto, que se referirão às entradas de chave e controle especificadas.
As ações de entrada são explicadas em detalhes na página Usando InputEvent.
Nota
Ao contrário da entrada do teclado, o suporte à entrada do mouse e do controle para uma ação (como olhar ao redor em um jogo em primeira pessoa) exigirá caminhos de código diferentes, pois devem ser tratados separadamente.
Qual método singleton de entrada devo usar?
Existem 3 maneiras de obter entrada com reconhecimento analógico:
Quando você tem dois eixos (como joystick ou movimento WASD) e deseja que ambos os eixos se comportem como uma única 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")
).limit_length(1.0)
// `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.
Vector2 velocity = Input.GetVector("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.
Vector2 velocity = new Vector2(
Input.GetActionStrength("move_right") - Input.GetActionStrength("move_left"),
Input.GetActionStrength("move_back") - Input.GetActionStrength("move_forward")
).LimitLength(1.0);
Quando você tem um eixo que pode funcionar em ambos os sentidos (como um acelerador em um stick de vôo), ou quando você deseja manipular eixos 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")
// `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");
Para outros tipos de entrada analógica, como manipulação de um gatilho ou manipulação de uma direção por 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")
// `strength` will be a floating-point number between `0.0` and `1.0`.
float strength = Input.GetActionStrength("accelerate");
Para entrada digital/booleana não analógica (apenas valores "pressionado" ou "não pressionado"), como botões do controle, botões do mouse ou teclas do 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");
Nota
If you need to know whether an input was just pressed in the previous
frame, use Input.is_action_just_pressed()
instead of
Input.is_action_pressed()
. Unlike Input.is_action_pressed()
which
returns true
as long as the input is
held, Input.is_action_just_pressed()
will only return true
for one
frame after the button has been pressed.
Vibration
Vibration (also called haptic feedback) can be used to enhance the feel of a game. For instance, in a racing game, you can convey the surface the car is currently driving on through vibration, or create a sudden vibration on a crash.
Use the Input singleton's start_joy_vibration method to start vibrating a gamepad. Use stop_joy_vibration to stop vibration early (useful if no duration was specified when starting).
On mobile devices, you can also use
vibrate_handheld to vibrate the
device itself (independently from the gamepad). On Android, this requires the
VIBRATE
permission to be enabled in the Android export preset before
exporting the project.
Nota
Vibration can be uncomfortable for certain players. Make sure to provide an in-game slider to disable vibration or reduce its intensity.
Diferenças entre teclado/mouse e entrada do controle
Se você está acostumado a lidar com entrada de teclado e mouse, pode se surpreender com a forma como os controles lidam com situações específicas.
Zona morta
Ao contrário dos teclados e mouses, os controles oferecem eixos com entradas analógicas. A vantagem das entradas analógicas é que elas oferecem flexibilidade adicional para ações. Ao contrário das entradas digitais que só podem fornecer intensidades de 0.0
e 1.0
, uma entrada analógica pode fornecer qualquer intensidade entre 0.0
e 1.0
. A desvantagem é que sem um sistema de zona morta, a força de um eixo analógico nunca será igual a 0.0
devido à forma como o controle é construído fisicamente. Em vez disso, ele permanecerá em um valor baixo, como 0.062
. Esse fenômeno é conhecido como drifting e pode ser mais perceptível em controles antigos ou com defeito.
Vamos pegar um jogo de corrida como um exemplo do mundo real. Graças às entradas analógicas, podemos dirigir o carro lentamente em uma direção ou outra. No entanto, sem um sistema de zona morta, o carro giraria lentamente sozinho, mesmo que o jogador não estivesse tocando o joystick. Isso ocorre porque a força do eixo direcional não será igual a 0.0
quando esperamos. Como não queremos que nosso carro gire sozinho neste caso, definimos um valor de "zona morta" de 0.2
que irá ignorar todas as entradas cuja força seja inferior a 0.2
. Um valor de zona morta ideal é alto o suficiente para ignorar a entrada causada pelo desvio do joystick, mas é baixo o suficiente para não ignorar a entrada real do jogador.
Godot features a built-in deadzone system to tackle this problem. The default
value is 0.5
, but you can adjust it on a per-action basis in the Project
Settings' Input Map tab. For Input.get_vector()
, the deadzone can be
specified as an optional 5th parameter. If not specified, it will calculate the
average deadzone value from all of the actions in the vector.
Eventos de "Eco"
Ao contrário da entrada do teclado, manter pressionado um botão do controle, como uma direção do D-pad, não gerará eventos de entrada repetidos em intervalos fixos (também conhecidos como eventos de "eco"). Isso ocorre porque o sistema operacional nunca envia eventos de "eco" para a entrada do controle em primeiro lugar.
Se você quiser que os botões do controlador enviem eventos de eco, você terá que gerar objetos InputEvent por código e analisá-los usando Input.parse_input_event() em intervalos regulares. Isso pode ser feito com a ajuda de um nó 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_APPLICATION_FOCUS_OUT:
focused = false
NOTIFICATION_APPLICATION_FOCUS_IN:
focused = true
func input_is_action_pressed(action: StringName) -> bool:
if focused:
return Input.is_action_pressed(action)
return false
func event_is_action_pressed(event: InputEvent, action: StringName) -> bool:
if focused:
return event.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.
On Linux, power saving prevention requires the engine to be able to use D-Bus. Check whether D-Bus is installed and reachable if running the project within a Flatpak, as sandboxing restrictions may make this impossible by default.
Solução de problemas
Ver também
Você pode ver uma lista de problemas conhecidos com suporte de controladores no GitHub.
Meu controle não é reconhecido pelo Godot.
Primeiro, verifique se seu controlador é reconhecido por outros aplicativos. Você pode usar o site Gamepad Tester para confirmar que seu controle é reconhecido.
On Windows Godot only supports up to 4 controllers at a time. This is because Godot uses the XInput API, which is limited to supporting 4 controllers at once. Additional controllers above this limit are ignored by Godot.
Meu controle funciona em uma determinada plataforma, mas não em outra plataforma.
Linux
If you're using a self-compiled engine binary, make sure it was compiled with
udev support. This is enabled by default, but it is possible to disable udev
support by specifying udev=no
on the SCons command line. If you're using an
engine binary supplied by a Linux distribution, double-check whether it was
compiled with udev support.
Controllers can still work without udev support, but it is less reliable as regular polling must be used to check for controllers being connected or disconnected during gameplay (hotplugging).
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.