CharacterBody2D/3D в Godot 4 — Полное руководство

1. Введение

В Godot 4 внесены серьёзные изменения в перемещение персонажей. Старые узлы KinematicBody2D и KinematicBody3D были переименованы в CharacterBody2D и CharacterBody3D, а API move_and_slide() был полностью переработан. Если вы переходите с Godot 3 или начинаете с нуля, это руководство охватывает всё необходимое.

CharacterBody2D и CharacterBody3D — это физические тела, предназначенные для персонажей, управляемых кодом. В отличие от RigidBody, они не реагируют на силы автоматически — вы полностью управляете их движением через скрипт. Это делает их идеальными для игровых персонажей, NPC и всего, что требует точного и детерминированного движения.

2. Что изменилось по сравнению с Godot 3

Вот наиболее важные изменения в перемещении персонажей между Godot 3 и Godot 4:

Ключевая мысль

В Godot 3 move_and_slide() возвращал итоговую скорость. В Godot 4 он возвращает bool (произошло ли столкновение), а скорость обновляется на месте в свойстве velocity.

3. Базовый 2D-контроллер платформера

Это стандартный контроллер платформера с горизонтальной прокруткой. Персонаж может двигаться влево/вправо и прыгать, находясь на земле. Это шаблон, который Godot генерирует при создании нового скрипта CharacterBody2D.

GDScript — platformer_controller.gd
extends CharacterBody2D

const SPEED = 300.0
const JUMP_VELOCITY = -400.0

func _physics_process(delta: float) -> void:
    # Apply gravity when not on floor
    if not is_on_floor():
        velocity += get_gravity() * delta

    # Jump when on floor and jump pressed
    if Input.is_action_just_pressed("ui_accept") and is_on_floor():
        velocity.y = JUMP_VELOCITY

    # Horizontal movement
    var direction := Input.get_axis("ui_left", "ui_right")
    if direction:
        velocity.x = direction * SPEED
    else:
        velocity.x = move_toward(velocity.x, 0, SPEED)

    move_and_slide()

Построчный разбор

Совет: необходимая структура узлов

Вашему CharacterBody2D нужен как минимум один дочерний узел CollisionShape2D с назначенной формой (например, RectangleShape2D или CapsuleShape2D). Без него move_and_slide() не будет обнаруживать никаких столкновений.

4. Базовый 2D-контроллер вида сверху

Для игр с видом сверху (RPG, twin-stick шутеры и т. д.) вы двигаетесь во всех четырёх направлениях без гравитации. Код проще, чем у платформера.

GDScript — topdown_controller.gd
extends CharacterBody2D

const SPEED = 200.0

func _physics_process(delta: float) -> void:
    var input_direction := Input.get_vector("ui_left", "ui_right", "ui_up", "ui_down")
    velocity = input_direction * SPEED
    move_and_slide()

Как это работает

Добавление ускорения и трения

Для более плавных ощущений с ускорением и замедлением:

GDScript — topdown_smooth.gd
extends CharacterBody2D

const SPEED = 200.0
const ACCELERATION = 1200.0
const FRICTION = 1000.0

func _physics_process(delta: float) -> void:
    var input_direction := Input.get_vector("ui_left", "ui_right", "ui_up", "ui_down")

    if input_direction != Vector2.ZERO:
        velocity = velocity.move_toward(input_direction * SPEED, ACCELERATION * delta)
    else:
        velocity = velocity.move_toward(Vector2.ZERO, FRICTION * delta)

    move_and_slide()

5. 3D-контроллер от третьего лица

3D-версия следует тому же паттерну. Основное отличие — работа с Vector3 и использование transform.basis для преобразования 2D-ввода в движение в 3D-мировом пространстве.

GDScript — character_3d.gd
extends CharacterBody3D

const SPEED = 5.0
const JUMP_VELOCITY = 4.5

func _physics_process(delta: float) -> void:
    # Apply gravity
    if not is_on_floor():
        velocity += get_gravity() * delta

    # Jump
    if Input.is_action_just_pressed("ui_accept") and is_on_floor():
        velocity.y = JUMP_VELOCITY

    # Get input and convert to 3D direction
    var input_dir := Input.get_vector("ui_left", "ui_right", "ui_up", "ui_down")
    var direction := (transform.basis * Vector3(input_dir.x, 0, input_dir.y)).normalized()

    if direction:
        velocity.x = direction.x * SPEED
        velocity.z = direction.z * SPEED
    else:
        velocity.x = move_toward(velocity.x, 0, SPEED)
        velocity.z = move_toward(velocity.z, 0, SPEED)

    move_and_slide()

Ключевые отличия от 2D

Предупреждение: get_gravity() требует Godot 4.4+

Метод get_gravity() был добавлен в Godot 4.4. Для более старых версий используйте Vector2(0, ProjectSettings.get_setting("physics/2d/default_gravity")) для 2D или Vector3(0, -ProjectSettings.get_setting("physics/3d/default_gravity"), 0) для 3D.

6. Справочник основных свойств

Как CharacterBody2D, так и CharacterBody3D имеют эти важные общие свойства. Настраивайте их в инспекторе или через код.

Свойство Тип По умолчанию Описание
velocity Vector2 / Vector3 Vector2.ZERO Скорость персонажа. Задайте её перед вызовом move_and_slide(). После вызова обновляется итоговой скоростью.
floor_snap_length float 1.0 Заменяет move_and_slide_with_snap(). Расстояние привязки персонажа к полу. Установите 0 для отключения. Полезно для склонов и лестниц.
up_direction Vector2 / Vector3 Vector2.UP Определяет, какое направление считается «вверх». Это определяет, что считается полом, стеной или потолком. По умолчанию (0, -1) в 2D, (0, 1, 0) в 3D.
floor_stop_on_slope bool true Когда true, персонаж не соскальзывает вниз по склонам, стоя на месте. Необходимо для платформеров.
floor_max_angle float 0.785 (45°) Максимальный проходимый угол склона в радианах. Поверхности круче этого значения считаются стенами. Используйте deg_to_rad(60), чтобы задать 60 градусов.
max_slides int 6 Максимальное число итераций столкновений за один вызов move_and_slide(). Более высокие значения точнее, но медленнее.
wall_min_slide_angle float 0.262 (15°) Минимальный угол для скольжения по стене. Предотвращает застревание персонажа на почти параллельных стенах.
platform_on_leave PlatformOnLeave ADD_VELOCITY Поведение при сходе с движущейся платформы. ADD_VELOCITY сохраняет импульс, ADD_UPWARD_VELOCITY добавляет только вертикальную составляющую, DO_NOTHING игнорирует скорость платформы.
slide_on_ceiling bool true Когда true, разрешает скольжение по потолкам. Когда false, останавливает горизонтальную скорость при ударе о потолок.

7. Обнаружение столкновений после move_and_slide()

После вызова move_and_slide() вы можете проанализировать произошедшие столкновения. Это полезно для реакции на конкретные типы коллайдеров, воспроизведения звуковых эффектов при приземлении или реализации механики прыжка от стены.

GDScript — collision_detection.gd
func _physics_process(delta: float) -> void:
    # ... set velocity here ...
    move_and_slide()

    # Check all collisions from this frame
    for i in get_slide_collision_count():
        var collision := get_slide_collision(i)
        var collider := collision.get_collider()
        print("Collided with: ", collider.name)
        print("Normal: ", collision.get_normal())
        print("Position: ", collision.get_position())

    # Practical example: bounce off enemies
    for i in get_slide_collision_count():
        var collision := get_slide_collision(i)
        if collision.get_collider().is_in_group("enemies"):
            velocity = collision.get_normal() * 300
            break

Полезные методы KinematicCollision

8. Шпаргалка по миграции

Быстрая справка по преобразованию кода Godot 3 в Godot 4:

Godot 3 Godot 4
KinematicBody2D CharacterBody2D
KinematicBody3D CharacterBody3D
velocity = move_and_slide(velocity, Vector2.UP) velocity = ...
move_and_slide()
move_and_slide_with_snap(vel, snap, up) floor_snap_length = 4.0
move_and_slide()
var vel = move_and_slide(...)
возвращает velocity
move_and_slide()
свойство velocity обновляется на месте
var gravity = ProjectSettings.get("physics/2d/default_gravity") get_gravity() (4.4+)
move_and_slide(..., up_direction, ...) up_direction = Vector2.UP (задаётся как свойство)
move_and_slide(..., stop_on_slope, ...) floor_stop_on_slope = true (задаётся как свойство)
Автоконвертер Godot

При открытии проекта Godot 3 в Godot 4 движок предлагает конвертировать проект. Он переименовывает узлы и пытается обновить скрипты, но не всегда правильно обрабатывает вызовы move_and_slide(). Скорее всего, вам придётся вручную исправить код перемещения.

9. Типичные ошибки

Ошибка 1: Передача аргументов в move_and_slide()

Неправильно
# ERROR: move_and_slide() takes no arguments in Godot 4
velocity = move_and_slide(velocity, Vector2.UP)
Правильно
# Set velocity, then call move_and_slide() with no arguments
velocity.x = direction * SPEED
move_and_slide()

Ошибка 2: Забывают задать velocity перед move_and_slide()

Неправильно — velocity никогда не задаётся, поэтому ничего не движется
func _physics_process(delta: float) -> void:
    move_and_slide()  # velocity is Vector2.ZERO — nothing happens

Ошибка 3: Использование _process() вместо _physics_process()

move_and_slide() должен вызываться в _physics_process(), который выполняется с фиксированной частотой (по умолчанию 60 Гц). Использование _process() привязывает физику к частоте кадров рендеринга, вызывая непоследовательное поведение.

Ошибка 4: Не настроен CollisionShape

CharacterBody2D/CharacterBody3D без дочернего CollisionShape будет проходить сквозь всё. Godot показывает значок предупреждения в редакторе, если форма столкновения отсутствует.

Ошибка 5: Перезапись velocity.y гравитацией каждый кадр

Неправильно — сбрасывает velocity.y, поэтому прыжок никогда не работает
# This overwrites any jump velocity!
velocity.y = gravity * delta  # should be +=, not =
Правильно — накапливает гравитацию
# Gravity accumulates over time
velocity += get_gravity() * delta

Ошибка 6: Применение гравитации, когда персонаж на полу

Всегда оборачивайте гравитацию в if not is_on_floor(). Без этой проверки гравитация продолжает накапливаться, пока персонаж на полу. Когда персонаж сходит с уступа, он будет падать с экстремальной скоростью вместо естественного падения.

10. Настройка контроллеров персонажей с помощью ИИ

Хотите, чтобы ИИ настроил ваш контроллер персонажа?

Godot MCP Pro позволяет ИИ-ассистентам создавать узлы CharacterBody, настраивать физические свойства, задавать формы столкновений, писать скрипты движения, запускать игру и тестировать движение — всё из запросов на естественном языке.

add_node setup_physics_body setup_collision set_physics_layers create_script simulate_key play_scene capture_frames
Получить Godot MCP Pro — $15