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<https://github.com/gabomdq/SDL_GameControllerDB>`__, отриманої від спільноти.
Контролери підтримуються у Windows, macOS, Linux, Android, iOS та HTML5.
Запримітьте, що більш спеціалізовані пристрої, такі як рульові колеса, педалі керма і HOTAS, менш перевірені і не завжди можуть працювати так, як очікувалося. Посилене тестування цих пристроїв також ще не реалізоване. Тому, якщо у вас є доступ до одного з цих пристроїв, не соромтеся `повідомляти про помилки на GitHub<https://github.com/godotengine/godot/blob/master/CONTRIBUTING.md#reporting-bugs>`__.
У цьому посібнику ви дізнаєтесь:
Як написати логіку введення для підтримки, як клавіатури, так і контролера.
Як контролери можуть поводитися інакше, ніж введення клавіатури/мишки.
Виправлення неполадок із контролерами в Godot.
Підтримка універсального введення¶
Завдяки своїй системі вхідних дій, Godot дозволяє підтримувати як введення з клавіатури, так і з контролера, без необхідності писати окремі шляхи коду. Замість жорсткого кодування клавіш, або кнопок контролера, у скриптах слід створити дії вводу в Параметрах проекту, які потім будуть посилатися на вказані вхідні дані клавіш та контролера.
Дії вводу детально пояснюються на сторінці Використання inputEvent.
Примітка
На відміну від введення з клавіатури, підтримка, як введення з мишки, так і з контролера, для дій (наприклад, озирнутися навколо в грі від першої особи) вимагатиме різних кодових шляхів, оскільки вони повинні оброблятися окремо.
Який метод singleton Input слід використовувати?¶
Існує 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.
Події "Відлуння"¶
На відміну від введення з клавіатури, утримування кнопку контролера, такої як напрямок D-pad, не буде генерувати повторювані події введення через фіксовані проміжки часу (також відомі як події "відлуння"). Це пов'язано з тим, що операційна система ніколи не надсилає події "відлуння" для введення з контролера.
Якщо ви хочете, щоб кнопки контролера надсилали події відлуння, вам доведеться генерувати об'єкти InputEvent в коді і аналізувати їх за допомогою Input.parse_input_event() через регулярні проміжки часу. Це можна зробити за допомогою вузла 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.
Вирішення проблем¶
Дивись також
Список `відомих проблем з підтримкою контролерів<https://github.com/godotengine/godot/issues?q=is%3Aopen+is%3Aissue+label%3Atopic%3Ainput+gamepad>`__ ви можете переглянути на GitHub.
Godot не розпізнає мій контролер.¶
По-перше, переконайтеся, що ваш контролер розпізнається іншими додатками. Ви можете використовувати веб-сайт Gamepad Tester, щоб переконатися, що ваш контролер розпізнається.
Мій контролер працює на даній платформі, але не на іншій платформі.¶
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 часто менш надійна в порівнянні з "рідними" платформами. Якість підтримки контролерів, як правило, сильно варіюється в різних браузерах. В результаті вам, можливо, доведеться доручити своїм гравцям використовувати інший браузер, якщо вони не можуть змусити свій контролер працювати.