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.

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

Godot поддерживает сотни моделей контроллеров "из коробки". Контроллеры поддерживаются на Windows, macOS, Linux, Android, iOS и в веб-версии.

Примечание

Начиная с версии Godot 4.5, движок использует SDL 3 для поддержки контроллеров в Windows, macOS и Linux. Это означает, что список поддерживаемых контроллеров и их поведение должны точно соответствовать тому, что доступно в других играх и движках, использующих SDL 3. Обратите внимание, что SDL используется только для ввода, а не для управления окнами или звука.

Prior to Godot 4.5, the engine used its own controller support code. This can cause certain controllers to behave incorrectly. This custom code is still used to support controllers on Android and Web, so it may result in issues appearing only on those platforms.

Примечание: более специализированные устройства, такие как рули, педали и HOTAS, менее протестированы и могут работать не так, как ожидалось. Переопределение силовой обратной связи для этих устройств также еще не реализовано. Если у вас есть доступ к одному из этих устройств, не стесняйтесь сообщать об ошибках на GitHub.

В этом руководстве вы узнаете:

  • Как написать логику ввода для поддержки ввода как с клавиатуры, так и с контроллера.

  • Как поведение контроллеров может отличаться от поведения клавиатуры/мыши.

  • Устранение неполадок с контроллерами в Godot.

Поддержка универсального ввода

Благодаря системе действий ввода Godot, Godot позволяет поддерживать ввод как с клавиатуры, так и с контроллера, без необходимости писать отдельные пути кода. Вместо жесткого кодирования клавиш или кнопок контроллера в ваших сценариях вам следует создать действия ввода в настройках проекта, которые затем будут ссылаться на указанные входы клавиш и контроллера.

Действия ввода подробно описаны на странице Использование InputEvent.

Примечание

В отличие от ввода с клавиатуры, поддержка ввода с помощью мыши и контроллера для действия (например, осмотра в игре от первого лица) потребует разных путей кода, поскольку они должны обрабатываться отдельно.

Какой singleton метод ввода я должен использовать?

Существует 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)
  • Если у вас есть одна ось, которая может двигаться в обе стороны (например, дроссель на ручке управления полетом), или когда вы хотите обрабатывать отдельные оси индивидуально, используйте 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")

Примечание

Если вам нужно узнать, было ли действие ввода только что совершено в предыдущем кадре, используйте Input.is_action_just_pressed() вместо Input.is_action_pressed(). В отличие от Input.is_action_pressed(), который возвращает true, пока кнопка зажата, Input.is_action_just_pressed() вернёт true только в течение одного кадра после нажатия кнопки.

Vibration (Вибрация)

Вибрация (также называемая тактильной обратной связью) может использоваться для усиления ощущений от игры. Например, в гоночной игре с помощью вибрации можно передать поверхность, по которой едет машина, или создать внезапную вибрацию при столкновении.

Используйте метод start_joy_vibration синглтона Input, чтобы запустить вибрацию геймпада. Используйте stop_joy_vibration, чтобы остановить вибрацию раньше (полезно, если при запуске не была указана длительность).

На мобильных устройствах вы также можете использовать vibrate_handheld, чтобы вибрировало само устройство (независимо от геймпада). На Android для этого требуется, чтобы разрешение VIBRATE было включено в пресете экспорта для Android перед экспортом проекта.

Примечание

Для некоторых игроков вибрация может вызывать дискомфорт. Обязательно предоставьте внутриигровой ползунок для отключения вибрации или уменьшения её интенсивности.

Различия между клавиатурой/мышью и вводом контроллера

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

Мертвая зона

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

В качестве реального примера возьмем гоночную игру. Благодаря аналоговым входам мы можем медленно направлять автомобиль в ту или иную сторону. Однако без системы мертвых зон автомобиль будет медленно двигаться сам по себе, даже если игрок не прикасается к джойстику. Это происходит потому, что сила оси направления не будет равна 0.0, когда мы этого ожидаем. Поскольку мы не хотим, чтобы в этом случае автомобиль управлялся сам по себе, мы определяем значение "мертвой зоны" 0.2, которое будет игнорировать все входные данные, сила которых меньше 0.2. Идеальное значение мертвой зоны достаточно высоко, чтобы игнорировать ввод, вызванный дрейфом джойстика, но достаточно низко, чтобы не игнорировать фактический ввод от игрока.

В Godot есть встроенная система мертвых зон для решения этой проблемы. Значение по умолчанию — 0.5, но вы можете настроить его для каждого действия отдельно во вкладке Input Map (Список действий) в Project Settings. Для Input.get_vector() мертвая зона может быть указана как необязательный 5-й параметр. Если он не указан, будет вычислено среднее значение мертвой зоны из всех действий в векторе.

"Эхо" события

В отличие от ввода с клавиатуры, удержание кнопки контроллера, например направления крестовины, не будет генерировать повторяющиеся события ввода через фиксированные интервалы (также известные как события «эха»). Это связано с тем, что операционная система вообще никогда не отправляет «эхо»-события для ввода контроллера.

Если вы хотите, чтобы кнопки контроллера отправляли события echo, вам придётся генерировать объекты InputEvent в коде и анализировать их с помощью Input.parse_input_event() с регулярными интервалами. Это можно сделать с помощью узла Timer.

Фокус окна

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

Хотя это полезно для стороннего функционала разделения экрана <https://nucleus-coop.github.io/>, это также может иметь негативные последствия. Игроки могут случайно отправить команды контроллера запущенному проекту, взаимодействуя с другим окном.

If you wish to ignore controller input events when the project isn't focused, set ProjectSettings.input_devices/joypads/ignore_joypad_on_unfocused_application to true. Alternatively, you can also set Input.ignore_joypad_on_unfocused_application to true.

Профилактика энергосбережения

В отличие от ввода с клавиатуры и мыши, ввод с контроллера не блокирует спящий режим и меры энергосбережения (например, выключение экрана по истечении определенного времени).

Чтобы решить эту проблему, Godot по умолчанию включает режим энергосбережения при запуске проекта. Если вы заметили, что система отключает дисплей при игре с геймпадом, проверьте значение параметра Display > Window > Energy Saving > Keep Screen On в настройках проекта.

Устранение неполадок

См. также

Вы можете просмотреть список известных проблем с поддержкой контроллера на GitHub.

Мой контроллер не распознается Годо.

Сначала проверьте, распознаётся ли ваш контроллер другими приложениями. Вы можете воспользоваться сайтом Gamepad Tester, чтобы убедиться, что ваш контроллер распознаётся.

В Windows Godot поддерживает не более 4 контроллеров одновременно. Это связано с тем, что Godot использует API XInput, который поддерживает только 4 контроллера одновременно. Дополнительные контроллеры, превышающие это ограничение, Godot игнорирует.

У моего контроллера неправильно назначены кнопки или оси.

Во-первых, если ваш контроллер предоставляет утилиту обновления прошивки, обязательно запустите её, чтобы получить последние исправления от производителя. Например, прошивку контроллеров Xbox One и Xbox Series можно обновить с помощью приложения Xbox Accessories app. (Это приложение работает только в Windows, поэтому для обновления прошивки контроллера вам потребуется компьютер с Windows или виртуальная машина Windows с поддержкой USB.) После обновления прошивки контроллера отсоедините контроллер от ПК и снова подключите его, если вы используете контроллер в беспроводном режиме.

Если кнопки назначены неправильно, это может быть связано с ошибочным назначением в базе данных игровых контроллеров SDL, используемой Godot, или в базе данных игровых контроллеров Godot <https://github.com/godotengine/godot/blob/master/core/input/godotcontrollerdb.txt>. В этом случае вам потребуется создать пользовательское назначение для вашего контроллера.

There are many ways to create mappings. One option is to start Steam in Big Picture mode, configure the controller and then look in config/config.vdf in the Steam installation directory for the SDL_GamepadBind entry. Another option is to use SDL's testcontroller application (the link only provides a Windows executable). Once you have a working mapping for your controller, you can test it by defining the SDL_GAMECONTROLLERCONFIG environment variable before running Godot:

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

Once you are satisfied with the custom mapping, you can contribute it for the next Godot version by opening a pull request on the Godot game controller database, or creating an issue in the Godot repository.

Since Godot uses SDL 3 for controller input, please consider contributing the mapping for the SDL library as well by opening a pull request on the official SDL gamepad database, or creating an issue in the SDL repository.

Примечание

Note that there are "generic" controllers on the market (usually their Input.get_joy_info(device)["raw_name"] property contains "USB Gamepad" string), and different generic controllers may use the same chipset, but they would have a different button placement, so creating a mapping for one of those controllers will most likely conflict with other ones, because the engine has no way of differentiating between controllers with the same chipset.

Мой контроллер работает на данной платформе, но не работает на другой платформе.

Linux

Если вы используете бинарный файл движка, скомпилированный самостоятельно, убедитесь, что он скомпилирован с поддержкой udev. Эта поддержка включена по умолчанию, но её можно отключить, указав udev=no в командной строке SCons. Если вы используете бинарный файл движка, поставляемый дистрибутивом Linux, дважды проверьте, скомпилирован ли он с поддержкой udev.

Контроллеры по-прежнему могут работать без поддержки udev, но это менее надежно, поскольку необходимо использовать регулярный опрос для проверки подключения или отключения контроллеров во время игры (горячее подключение).

Android

Как описано в начале страницы, поддержка контроллеров на мобильных платформах основана на пользовательской реализации, а не на использовании SDL для ввода данных. Это означает, что поддержка контроллеров может быть менее надёжной, чем на настольных платформах.

Support for SDL-based controller input on mobile platforms is planned in a future release.

Web

Поддержка Web-контроллеров зачастую менее надёжна по сравнению с "родными" платформами. Качество поддержки контроллеров, как правило, сильно различается в разных браузерах. В результате вам, возможно, придётся попросить игроков использовать другой браузер, если у них не получится запустить контроллер.

Like for mobile platforms, support for SDL-based controller input on the web platform is planned in a future release.