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...
Контроллеры, геймпады и джойстики
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)
// `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");
Примечание
Если вам нужно узнать, было ли действие ввода только что совершено в предыдущем кадре, используйте 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 игнорирует.
Мой контроллер работает на данной платформе, но не работает на другой платформе.
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.