Up to date
This page is up to date for Godot 4.2
.
If you still find outdated information, please open an issue.
Контроллеры, геймпады и джойстики¶
Godot поддерживает сотни моделей контроллеров благодаря созданной сообществом базе данных игровых контроллеров SDL.
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. Overriding force feedback for those devices is also not implemented yet. If you have access to one of those devices, don't hesitate to report bugs on GitHub.
В этом руководстве вы узнаете:
Как написать логику ввода для поддержки ввода как с клавиатуры, так и с контроллера.
How controllers can behave differently from keyboard/mouse input.
Устранение неполадок с контроллерами в Godot.
Supporting universal input¶
Благодаря системе действий ввода Godot, Godot позволяет поддерживать ввод как с клавиатуры, так и с контроллера, без необходимости писать отдельные пути кода. Вместо жесткого кодирования клавиш или кнопок контроллера в ваших сценариях вам следует создать действия ввода в настройках проекта, которые затем будут ссылаться на указанные входы клавиш и контроллера.
Действия ввода подробно описаны на странице Использование InputEvent.
Примечание
В отличие от ввода с клавиатуры, поддержка ввода с помощью мыши и контроллера для действия (например, осмотра в игре от первого лица) потребует разных путей кода, поскольку они должны обрабатываться отдельно.
Which Input singleton method should I use?¶
Существует 3 способа получения аналогового ввода:
Если у вас есть две оси (например, джойстик или движение WASD) и вы хотите, чтобы обе оси вели себя как один вход, используйте
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);
Если у вас есть одна ось, которая может двигаться в обе стороны (например, дроссель на ручке управления полетом), или когда вы хотите обрабатывать отдельные оси индивидуально, используйте
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");
Для других типов аналогового ввода, таких как обработка триггера или обработка одного направления за раз, используйте
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");
Для неаналогового цифрового/логического ввода (только значения «нажато» или «не нажато»), например кнопок контроллера, кнопок мыши или клавиш клавиатуры, используйте 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");
Примечание
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.
В версиях Godot до 3.4, таких как 3.3, Input.get_vector()
и Input.get_axis()
недоступны. В Godot 3.3 доступны только Input.get_action_strength()
и Input.is_action_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.
Примечание
Vibration can be uncomfortable for certain players. Make sure to provide an in-game slider to disable vibration or reduce its intensity.
Различия между клавиатурой/мышью и вводом контроллера¶
Если вы привыкли обрабатывать ввод с клавиатуры и мыши, вы можете быть удивлены тем, как контроллеры справляются с конкретными ситуациями.
Мертвая зона¶
В отличие от клавиатур и мышей, контроллеры предлагают оси с аналоговыми входами. Преимущество аналоговых входов в том, что они обеспечивают дополнительную гибкость действий. В отличие от цифровых входов, которые могут обеспечить силу только 0.0
и 1.0
, аналоговый вход может обеспечить любую силу между 0.0
и 1.0
. Недостатком является то, что без системы мертвых зон сила аналоговой оси никогда не будет равна 0.0
из-за того, как физически построен контроллер. Вместо этого она будет задерживаться на низком значении, таком как 0.062
. Это явление известно как дрейф и может быть более заметно на старых или неисправных контроллерах.
В качестве реального примера возьмем гоночную игру. Благодаря аналоговым входам мы можем медленно направлять автомобиль в ту или иную сторону. Однако без системы мертвых зон автомобиль будет медленно двигаться сам по себе, даже если игрок не прикасается к джойстику. Это происходит потому, что сила оси направления не будет равна 0.0
, когда мы этого ожидаем. Поскольку мы не хотим, чтобы в этом случае автомобиль управлялся сам по себе, мы определяем значение "мертвой зоны" 0.2
, которое будет игнорировать все входные данные, сила которых меньше 0.2
. Идеальное значение мертвой зоны достаточно высоко, чтобы игнорировать ввод, вызванный дрейфом джойстика, но достаточно низко, чтобы не игнорировать фактический ввод от игрока.
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.
"Echo" events¶
В отличие от ввода с клавиатуры, удержание кнопки контроллера, например направления крестовины, не будет генерировать повторяющиеся события ввода через фиксированные интервалы (также известные как события «эха»). Это связано с тем, что операционная система вообще никогда не отправляет «эхо»-события для ввода контроллера.
Если вы хотите, чтобы кнопки контроллера отправляли эхо-события, вам придется генерировать объекты InputEvent с помощью кода и анализировать их с помощью Input.parse_input_event() через регулярные промежутки времени. Это можно сделать с помощью узла class_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.
Устранение неполадок¶
См.также
You can view a list of known issues with controller support on GitHub.
Мой контроллер не распознается Годо.¶
Сначала убедитесь, что ваш контроллер распознается другими приложениями. Вы можете использовать веб-сайт Gamepad Tester, чтобы убедиться, что ваш контроллер распознан.
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.
Мой контроллер работает на данной платформе, но не работает на другой платформе.¶
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 часто менее надежна по сравнению с «родными» платформами. Качество поддержки контроллеров сильно различается в разных браузерах. В результате вам, возможно, придется поручить своим игрокам использовать другой браузер, если они не смогут заставить свой контроллер работать.