Камера от третьего лица с пружинным рычагом

Введение

В 3D-играх часто используется камера от третьего лица, которая следует за персонажем игрока или транспортным средством и вращается вокруг него.

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

Вот тут-то и пригодится узел SpringArm3D.

Что такое пружинный рычаг?

Пружинный рычаг состоит из двух основных компонентов, которые влияют на его поведение.

«Длина» пружинного рычага — это расстояние от его глобального положения, на котором необходимо проверять наличие столкновений:

../../_images/spring_arm_position_length.webp

«Форма» пружинного рычага — это то, что он использует для проверки столкновений. Пружинный рычаг «выметает» эту форму от ее начала по направлению к ее длине.

../../_images/spring_arm_shape.webp

Пружинный рычаг пытается удержать всех своих потомков в конце своей длины. Когда форма сталкивается с чем-то, потомки вместо этого размещаются в точке столкновения или около нее:

../../_images/spring_arm_children.webp

Пружинный рычаг с камерой

Если камера размещена как дочерний элемент пружинного рычага, в качестве формы будет использоваться пирамида, представляющая камеру.

Эта пирамида представляет собой near plane (ближнюю плоскость) камеры:

../../_images/spring_arm_camera_shape.webp

Примечание

Если пружинному рычагу придать определенную форму, то эта форма будет использоваться всегда.

Форма камеры используется только в том случае, если камера является прямым потомком пружинного рычага.

Если форма не указана и камера не является прямым потомком, пружинный рычаг вернется к использованию луча, что неточно для столкновений камер и не рекомендуется.

В каждом кадре физического процесса пружинный рычаг будет выполнять приведение движения, чтобы проверить, сталкивается ли с чем-либо:

../../_images/spring_arm_camera_motion_cast.webp

Когда фигура сталкивается с чем-либо, камера будет помещена в точку столкновения или рядом с ней:

../../_images/spring_arm_camera_collision.webp

Установка пружинного рычага и камеры

Давайте добавим в демо-версию платформера камеру с пружинным рычагом.

Примечание

Вы можете загрузить демоверсию Platformer 3D на GitHub или с помощью Asset Library.

В общем случае для настройки камеры от третьего лица у вас будет три узла в качестве дочерних узлов узла, за которым вы следите:

  • Node3D («точка опоры» для камеры)

    • SpringArm3D

      • Camera3D

Откройте сцену player/player.tscn. Настройте их как дочерние элементы нашего игрока и дайте им уникальные имена, чтобы мы могли найти их в нашем скрипте. Обязательно удалите существующий узел камеры!

../../_images/spring_arm_editor_setup.webp

Давайте переместим точку опоры на 2 вверх по оси Y, чтобы она не находилась на земле:

../../_images/spring_arm_pivot_setup.webp

Придайте пружинному рычагу длину 3, чтобы он располагался позади персонажа:

../../_images/spring_arm_length_setup.webp

Примечание

Оставьте Shape (Форму) пружинного рычага как <empty>. Таким образом, он будет использовать форму пирамиды камеры.

При желании вы можете попробовать и другие формы — сфера является распространенным выбором, поскольку она плавно скользит по краям.

Обновите верхнюю часть player/player.gd, чтобы получить камеру и точки поворота по их уникальным именам:

player/player.gd
# Comment out this existing camera line.
# @onready var _camera := $Target/Camera3D as Camera3D

@onready var _camera := %Camera3D as Camera3D
@onready var _camera_pivot := %CameraPivot as Node3D

Добавьте функцию _unhandled_input для проверки движения камеры, а затем поверните точку поворота соответствующим образом:

player/player.gd
@export_range(0.0, 1.0) var mouse_sensitivity = 0.01
@export var tilt_limit = deg_to_rad(75)


func _unhandled_input(event: InputEvent) -> void:
    if event is InputEventMouseMotion:
        _camera_pivot.rotation.x -= event.relative.y * mouse_sensitivity
        # Prevent the camera from rotating too far up or down.
        _camera_pivot.rotation.x = clampf(_camera_pivot.rotation.x, -tilt_limit, tilt_limit)
        _camera_pivot.rotation.y += -event.relative.x * mouse_sensitivity

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