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 поддерживает уникальные особенности контроллеров для улучшения игрового опыта. Данная страница описывает эти особенности, как их реализовывали в уже существующих играх и как вы можете начать с ними работать в Godot.
Предупреждение
Эти функции контроллера в настоящее время поддерживаются только в Windows, macOS, iOS и Linux.
Предупреждение
Если вы не продвигаете свою игру как требующую определённый вид контроллеров, то помните: нет гарантии, что у игроков есть необходимое устройство с той или иной особенностью.
Как итог, мы рекомендуем применять эти особенности лишь для улучшения игрового опыта тех игроков, чьи контроллеры их поддерживают, без отторжения тех, у кого отсутствуют те или иные контроллеры.
Цвет светодиода
Игры могут использовать светодиодную подсветку на некоторых контроллерах для небольшого дополнения происходящего на экране посредством соответствия визуального стиля в руках игрока. Вот несколько ключевых примеров:
В Hades цвет подсветки соответствуют божеству, которое вручает вам дар.
В Resident Evil 2 цвет подсветки отражает ваше здоровье (зелёный при полном, жёлтый при среднем и красный при малом количестве здоровья).
В Star Wars Jedi: Fallen Order цвет подсветки соответствует цвету светового меча.
Используйте метод Input.set_joy_light() для установки необходимого цвета.
Чтобы определить, поддерживает ли данный контроллер установку светодиодной подсветки, используйте метод Input.has_joy_light(). Известно, что контроллеры PlayStation DualShock и DualSense поддерживают светодиодную подсветку.
Следующий метод _process() устанавливает цвет светодиода в зависимости от текущей нажатой кнопки и выключает его, если кнопка не нажата:
func _process(_delta):
var color := Color.BLACK
if Input.is_joy_button_pressed(0, JOY_BUTTON_A):
color = Color.BLUE
elif Input.is_joy_button_pressed(0, JOY_BUTTON_X):
color = Color.MAGENTA
elif Input.is_joy_button_pressed(0, JOY_BUTTON_B):
color = Color.RED
elif Input.is_joy_button_pressed(0, JOY_BUTTON_Y):
color = Color.GREEN
Input.set_joy_light(0, color)
В следующем примере светодиод плавно меняет цвет в цикле:
var hue = 0.0
func _process(delta):
var col = Color.from_hsv(hue, 1.0, 1.0)
Input.set_joy_light(0, col)
hue += delta * 0.1
В следующем примере светодиод трижды мигает красным при нажатии южной кнопки (Крест/X на контроллерах PlayStation):
var blink_tween: Tween = null
func _process(_delta):
var ready_to_blink = not blink_tween or not blink_tween.is_running()
if Input.is_joy_button_pressed(0, JOY_BUTTON_A) and ready_to_blink:
do_blink()
func do_blink():
if blink_tween:
blink_tween.kill()
blink_tween = create_tween()
blink_tween.tween_callback(func(): Input.set_joy_light(0, Color.RED))
blink_tween.tween_interval(0.2)
blink_tween.tween_callback(func(): Input.set_joy_light(0, Color.BLACK))
blink_tween.tween_interval(0.2)
blink_tween.set_loops(3)
Датчики движения (гироскоп и акселерометр)
Благодаря управлению движением, игры могут отслеживать физическое вращение и перемещение контроллера. Это позволяет игроку поворачивать внутриигровую камеру, двигая контроллером, или встряхивать его для выполнения специального действия.
Несколько производителей контроллеров интегрировали гироскопы и акселерометры в свои современные устройства, двумя крупнейшими из которых являются PlayStation и Nintendo. Следует отметить, что контроллеры Xbox не имеют встроенных датчиков движения.
Чтобы проверить наличие датчиков движения у подключенного контроллера, используйте Input.has_joy_motion_sensors().
Датчики движения по умолчанию отключены, чтобы избежать разрядки батареи контроллера, когда игры не используют эти функции. Чтобы включить их, вызовите команду Input.set_joy_motion_sensors_enabled().
Обратите внимание, что оси значений, сообщаемых датчиками движения контроллера, всегда отсчитываются относительно естественной ориентации контроллера. Для большей наглядности приведено изображение, показывающее отображение осей:
Значения гироскопа контроллера показывают вращение вокруг соответствующих осей:
the X value of the gyroscope data shows the rotation around the X axis (pitch).
Y значение гироскопа показывает вращение вокруг оси Y (yaw).
the Z value of the gyroscope data shows the rotation around the Z axis (roll).
Акселерометр контроллера будет предоставлять значения следующими способами:
Движение влево и вправо передаются как +X и -X.
Движение вниз и вверх передаются как +Y и -Y.
Перемещения от пользователя и к пользователю передаются как +Z и -Z.
Гироскоп
Гироскоп — это тип датчика, который определяет вращение контроллера. Вот несколько примечательных примеров использования гироскопа в играх:
В Helldivers 2, Horizon Forbidden West, Star Wars: Dark Forces Remaster и Fortnite наклон контроллера заставляет камеру вращаться соответствующим образом ("гироскопическое прицеливание"). Это видео от *Daven On The Moon* демонстрирует и обсуждает гироскопическое прицеливание более подробно.
В Death Stranding BB можно успокоить, мягко вращая контроллер.
В следующем примере объект вращается с помощью датчика гироскопа контроллера. Вы также можете ознакомиться с этим примером, взглянув на документацию Input.start_joy_motion_sensors_calibration().
const GYRO_SENSITIVITY = 10.0
func _ready():
# In this example we only use the first connected joypad (id 0).
if 0 not in Input.get_connected_joypads():
return
if not Input.has_joy_motion_sensors(0):
return
# We must enable the motion sensors before using them.
Input.set_joy_motion_sensors_enabled(0, true)
# (Tell the users here that they need to put their joypads on a flat surface and wait for confirmation.)
# Start the calibration process.
calibrate_motion()
func _process(delta):
# Only move the object if the joypad motion sensors are calibrated.
if Input.is_joy_motion_sensors_calibrated(0):
move_object(delta)
func calibrate_motion():
Input.start_joy_motion_sensors_calibration(0)
# Wait for some time.
await get_tree().create_timer(1.0).timeout
Input.stop_joy_motion_sensors_calibration(0)
# The joypad is now calibrated.
func move_object(delta):
var node: Node3D = ... # Put your object here.
var gyro := Input.get_joy_gyroscope(0)
node.rotation.x -= -gyro.y * GYRO_SENSITIVITY * delta # Use rotation around the Y axis (yaw) here.
node.rotation.y += -gyro.x * GYRO_SENSITIVITY * delta # Use rotation around the X axis (pitch) here.
Обратите внимание, что перед использованием данных гироскопа мы должны сначала откалибровать его, вызвав Input.start_joy_motion_sensors_calibration() и Input.stop_joy_motion_sensors_calibration(). Это связано с тем, что современные гироскопы часто нуждаются в калибровке. Это похоже на то, как весам может потребоваться калибровка, чтобы указать, что такое "ноль". Как и весы, только правильно откалиброванный гироскоп даст точные показания. Во время калибровки пользователь кладёт контроллер на ровную поверхность. Затем контроллер определяет, какие значения сообщает его гироскоп, когда он вообще не движется (его "смещение"), и использует эту информацию для повышения точности данных о вращении.
См. статью на GyroWiki для получения информации о том, как использовать ввод с гироскопа в качестве мыши.
После того как гироскоп контроллера будет включён и правильно откалиброван, вы можете считывать его показания с помощью Input.get_joy_gyroscope().
Акселерометр
Предупреждение
Не используйте данные акселерометра для определения положения контроллера в 3D-пространстве; акселерометры в целом недостаточно точны для этого.
Акселерометр — это тип датчика, который определяет ускорение контроллера в м/с². Например, он может определить, быстро ли игрок поднимает контроллер, двигает его в сторону или встряхивает.
Ускорение, определяемое акселерометром, по умолчанию включает гравитацию. Чтобы получить только ускорение, сообщённое пользователем, вычтите гравитацию из измеренного ускорения:
Input.get_joy_accelerometer(device) - Input.get_joy_gravity(device)
Из-за физических особенностей работы акселерометров после остановки движения в одном направлении они почти сразу сообщают о движении в противоположном направлении. После обнаружения движения в одном направлении вы можете захотеть игнорировать дальнейшие показания в течение короткого периода времени, чтобы избежать обнаружения этого противоположного движения.
В следующем примере выводится движение контроллера при его быстром перемещении с помощью акселерометра. Если чувствительность кажется вам неподходящей, вы можете настроить константу THRESHOLD или заменить её на другое значение в коде ниже.
var detect_accelerometer = true
# Change to make the game detect movement at different thresholds.
# With a lower value, smaller movements will be detected, and with a
# larger value, only big movements will be detected.
const THRESHOLD = 10.0
func _ready():
# In this example, we only use the first connected joypad (ID 0).
if 0 not in Input.get_connected_joypads():
return
if not Input.has_joy_motion_sensors(0):
return
# We must enable the motion sensors before using them.
Input.set_joy_motion_sensors_enabled(0, true)
func _process(delta):
if Input.has_joy_motion_sensors(0):
accelerometer_example()
func accelerometer_example():
if not detect_accelerometer:
return
var acceleration = Input.get_joy_accelerometer(0) - Input.get_joy_gravity(0)
if acceleration.length() > THRESHOLD:
if acceleration.x > THRESHOLD:
print("Moved left")
elif acceleration.x < -THRESHOLD:
print("Moved right")
if acceleration.y < -THRESHOLD:
print("Moved up")
elif acceleration.y > THRESHOLD:
print("Moved down")
if acceleration.z < -THRESHOLD:
print("Moved closer to the player")
elif acceleration.z > THRESHOLD:
print("Moved away from the player")
# After detecting movement in one direction, the accelerometer sensor
# will briefly report movement in the opposite direction, even though the controller only moved once.
# So we need to ignore these reported values for a short amount of time.
detect_accelerometer = false
await get_tree().create_timer(0.5, false).timeout
detect_accelerometer = true