Контролери, геймпади та джойстики

Godot підтримує сотні моделей контролерів завдяки `базі даних ігрових контролерів SDL<https://github.com/gabomdq/SDL_GameControllerDB>`__, отриманої від спільноти.

Контролери підтримуються у Windows, macOS, Linux, Android, iOS та 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.

У цьому посібнику ви дізнаєтесь:

  • Як написати логіку введення для підтримки, як клавіатури, так і контролера.

  • Як контролери можуть поводитися інакше, ніж введення клавіатури/мишки.

  • Виправлення неполадок із контролерами в 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")).clamped(1)
  • Якщо у вас є одна вісь, яка може ходити в обох напрямках (наприклад, дросельна заслінка на льотній палиці), або коли ви хочете обробляти окремі осі окремо, використовуйте 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")
  • Для інших типів аналогового входу, таких як обробка спускового гачка, або обробка одного напрямку за раз, використовуйте Input.get_action_strength():

# `strength` will be a floating-point number between `0.0` and `1.0`.
var strength = Input.get_action_strength("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");

У версіях Godot до версії 3.4, наприклад 3.3, Input.get_vector() і Input.get_axis() недоступні. В Godot 3.3 доступні тільки Input.get_action_strength() і Input.is_action_pressed().

Відмінності між введенням клавіатури/мишки та контролера

Якщо ви звикли обробляти введення з клавіатури та миші, ви можете бути здивовані тим, як контролери справляються з певними ситуаціями.

Мертва зона

На відміну від клавіатур і мишок, контролери пропонують осі з аналоговими входами. Перевага аналогових входів полягає в тому, що вони пропонують додаткову гнучкість для дій. На відміну від цифрових входів, які можуть забезпечити силу тільки 0.0 і 1.0, аналоговий вхід може забезпечити будь-яку силу між 0.0 і 1.0. Недоліком є те, що без системи мертвої зони сила аналогової осі ніколи не зрівняється з 0.0 черех фізичну будову контролера. Замість цього він затримається на низькому значенні, такому як 0.062. Це явище відоме як дрейфування і може бути більш помітним на старих, або несправних, контролерах.

Візьмемо гоночну гру як реальний приклад. Завдяки аналоговим входам ми можемо повільно направляти машину в ту, чи іншу, сторону. Однак без системи мертвої зони автомобіль повільно буде рухатися сам по собі, навіть якщо гравець не торкається джойстика. Це пояснюється тим, що сила спрямованої осі не буде дорівнювати 0.0, коли ми того очікуємо. Оскільки ми не хочемо, щоб наш автомобіль їхав сам по собі, ми визначаємо значення "мертвої зони" 0.2, яке буде ігнорувати всі вхідні дані, сила яких нижче, ніж 0.2. Ідеальне значення мертвої зони має бути досить високе, щоб ігнорувати введення джойстика, яке спричиняє дрейфування, але досить низьке, щоб не ігнорувати фактичний ввід гравця.

Godot має вбудовану систему мертвих зон для вирішення цієї проблеми. Значення за промовчанням – 0.2, але його можна збільшити, або зменшити, для кожної дії на вкладці Карта введення в Параметрах проекту. Для Input.get_vector(), мертва зона може бути вказана, або, в іншому випадку, вона буде обчислювати середнє значення мертвої зони з усіх дій у векторі.

Події "Відлуння"

На відміну від введення з клавіатури, утримування кнопку контролера, такої як напрямок D-pad, не буде генерувати повторювані події введення через фіксовані проміжки часу (також відомі як події "відлуння"). Це пов'язано з тим, що операційна система ніколи не надсилає події "відлуння" для введення з контролера.

Якщо ви хочете, щоб кнопки контролера надсилали події відлуння, вам доведеться генерувати об'єкти InputEvent в коді і аналізувати їх за допомогою Input.parse_input_event() через регулярні проміжки часу. Це можна зробити за допомогою вузла Timer.

Вирішення проблем

Godot не розпізнає мій контролер.

По-перше, переконайтеся, що ваш контролер розпізнається іншими додатками. Ви можете використовувати веб-сайт Gamepad Tester, щоб переконатися, що ваш контролер розпізнається.

На моєму контролері неправильно зіставлені кнопки, або осі.

Якщо кнопки зіставлені неправильно, це може бути пов'язано з помилковим зіставленням в `базі даних ігрового контролера SDL<https://github.com/gabomdq/SDL_GameControllerDB>`__. Ви можете внести оновлене зіставлення, яке буде включено до наступної версії Godot, відкривши запит на проблему у пов'язаному сховищі.

Існує багато способів створення зіставлень. Одним з варіантів є використання майстра зіставлень в офіційній демонстрації Joypads. Після того, як у вас буде робоче зіставлення для вашого контролера, ви можете протестувати його, визначивши змінну середовища SDL_GAMECONTROLLERCONFIG перед запуском Godot:

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

Щоб перевірити зіставлення на платформах без настільних комп'ютерів, або розповсюдити проект з додатковими зіставленнями контролерів, ви можете додати їх викликавши Input.add_joy_mapping(), якомога раніше у функції скрипту _ready().

Мій контролер працює на даній платформі, але не на іншій платформі.

Linux

До Godot 3.3 офіційні бінарні файли Godot були складені з підтримкою udev, але самостійно складені бінарні файли були складені без підтримки udev, якщо udev=yes не було передано в командному рядку SCons. Це зробило підтримку плагінів контролера недоступною в самостійно скомпільованих бінарних файлах.

HTML5

Підтримка контролерів HTML5 часто менш надійна в порівнянні з "рідними" платформами. Якість підтримки контролерів, як правило, сильно варіюється в різних браузерах. В результаті вам, можливо, доведеться доручити своїм гравцям використовувати інший браузер, якщо вони не можуть змусити свій контролер працювати.

Також зверніть увагу, що `підтримка контролерів була значно покращена<https://github.com/godotengine/godot/pull/45078>`__ в Godot 3.3 і пізніших версіях.