Up to date

This page is up to date for Godot 4.2. If you still find outdated information, please open an issue.

Кинематический персонаж (2D)

Введение

Да, название звучит странно. «Кинематический персонаж». Что это? Причина такого названия в том, что когда появились физические движки, они назывались движками динамики (потому что они работали в основном с реакцией на столкновения). Было предпринято много попыток создать контроллер персонажа, используя движки динамики, но это оказалось не так просто, как казалось. Godot имеет одну из лучших реализаций динамического контроллера персонажа, которую вы можете найти (это можно увидеть в демонстрации 2d/платформера), но ее использование требует значительного уровня мастерства и понимания физических движков (или большого терпения на пробы и ошибки).

Некоторые физические движки, такие, как Havok, преподносят динамические контроллеры персонажей как лучший вариант, в то же время как другие (PhysX), напротив, продвигают только кинематику.

Так, а в чём разница?:

  • Динамический контроллер персонажа использует твёрдое тело с бесконечным тензором инерции. Это твёрдое тело, которое не может вращаться. Физические движки всегда позволяют объектам двигаться и сталкиваться, а затем решают их столкновения разом. Это делает динамические контроллеры персонажей способными бесшовно взаимодействовать с другими объектами физики, как показано в демо-версии платформера. Однако, эти взаимодействия не всегда предсказуемы. Столкновения могут длиться более одного кадра для завершения расчётов, и несколько столкновений могут оказаться смещёнными на несколько бит. Эти проблемы могут быть устранены, но требуют определенной квалификации.

  • Предполагается, что контроллер кинематических персонажей всегда начинает в состоянии отсутствия столкновений и всегда переходит в состояние отсутствия столкновений. Если он начнёт в состоянии столкновения, то он попытается освободиться, как это делают твёрдые тела, но это исключение, а не правило. Это делает управление им и движение гораздо более предсказуемыми и более простыми в программировании. Однако, как недостаток, он не может напрямую взаимодействовать с другими физическими объектами, если это не делается вручную в коде.

This short tutorial focuses on the kinematic character controller. It uses the old-school way of handling collisions, which is not necessarily simpler under the hood, but well hidden and presented as an API.

Обработка физики

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

extends CharacterBody2D

func _physics_process(delta):
    pass

Настройка сцены

To have something to test, here's the scene (from the tilemap tutorial): kinematic_character_2d_starter.zip. We'll be creating a new scene for the character. Use the robot sprite and create a scene like this:

../../_images/kbscene.webp

Вы заметите, что рядом с нашим узлом CollisionShape2D есть значок предупреждения; это потому, что мы не определили форму для него. Создайте новый CircleShape2D в свойстве формы CollisionShape2D. Нажмите кнопку < CircleShape2D >, чтобы перейти к его параметрам, и установите радиус, равный 30:

../../_images/kbradius.webp

Внимание: Как упоминалось выше в учебном пособии по физике, модуль физики не может обрабатывать масштаб на большинстве типов форм (работают только многоугольники столкновений, плоскости и сегменты), поэтому всегда изменяйте параметры (например, радиус) формы вместо её масштабирования. То же самое справедливо и для самих кинематических/жёстких/статических тел, поскольку их масштаб влияет на масштаб формы.

Теперь создайте скрипт для персонажа, который использовался в качестве примера выше и должен работать, как изначально.

Наконец, инстанцируйте эту сцену персонажа в tilemap и сделайте сцену карты главной, чтобы она запускалась при нажатии на воспроизведение.

../../_images/kbinstance.webp

Перемещение кинематического персонажа

Go back to the character scene, and open the script, the magic begins now! Kinematic body will do nothing by default, but it has a useful function called CharacterBody2D.move_and_collide(). This function takes a Vector2 as an argument, and tries to apply that motion to the kinematic body. If a collision happens, it stops right at the moment of the collision.

Итак, давайте сдвинем наш спрайт вниз, пока он не ударится об пол:

extends CharacterBody2D

func _physics_process(delta):
    move_and_collide(Vector2(0, 1)) # Move down 1 pixel per physics frame

В результате персонаж двигается, но останавливается прямо при ударе о пол. Довольно круто, да?

Следующим шагом будет добавление гравитации к миксу, путь он ведет себя немного ближе к обычному игровому персонажу:

extends CharacterBody2D

const GRAVITY = 200.0

func _physics_process(delta):
    velocity.y += delta * GRAVITY

    var motion = velocity * delta
    move_and_collide(motion)

Теперь персонаж плавно падает. Давайте заставим его идти в стороны, влево и вправо при нажатии на клавиши управления. Следует помнить, что используемые значения (по крайней мере для скорости) составляют пикселы в секунду.

This adds basic support for walking when pressing left and right:

extends CharacterBody2D

const GRAVITY = 200.0
const WALK_SPEED = 200

func _physics_process(delta):
    velocity.y += delta * GRAVITY

    if Input.is_action_pressed("ui_left"):
        velocity.x = -WALK_SPEED
    elif Input.is_action_pressed("ui_right"):
        velocity.x =  WALK_SPEED
    else:
        velocity.x = 0

    # "move_and_slide" already takes delta time into account.
    move_and_slide()

И попробуем.

Это хорошая отправная точка для платформера. Более полную демонстрацию можно найти в demo zip, распространяемом вместе с движком, или в https://github.com/godotengine/godot-demo-projects/tree/master/2d/kinematic_character.