Движение игрока в Godot: руководство по CharacterBody2D и GDScript

Коротко: в Godot 4 для 2D-игр используйте узел CharacterBody2D и GDScript для обработки ввода, расчёта вектора скорости и вызова методов перемещения (move_and_collide или move_and_slide). В статье показаны примеры для клавиатуры и мыши, варианты поворота, советы по плавности движения, альтернативы и чеклисты для команды.
Важно: все примеры написаны для Godot 4 и предполагают, что вы используете InputMap (Actions) для привязки клавиш и мыши.
Зачем это нужно
Реализация управления игроком — основа геймплея. От качества движения зависят ощущения игрока, управление камерой и взаимодействие с окружением. Правильная архитектура кода упрощает добавление прыжков, рывков, физики и анимаций.
Быстрый план статьи
- Настройка проекта и сцены
- Перемещение по клавиатуре (код и разъяснение)
- Поворот в сторону движения
- Перемещение и поворот по мыши
- Дополнительные механики: прыжок, рывок, скольжение по стене
- Лучшие практики, альтернативы и кейсы приёмки
- Чеклисты для ролей, глоссарий и FAQ
Настройка Godot-проекта и сцены
- Создайте новый 2D-проект в Godot.
- В панели FileSystem создайте папку Scenes и сохраните сцену как Player.tscn.
- Добавьте узел CharacterBody2D в сцену.
- Внутри CharacterBody2D добавьте CollisionShape2D и настройте форму (прямоугольник или капсула по размеру спрайта).
- Добавьте Sprite2D и выберите спрайт персонажа.
Совет: используйте InputMap (Project Settings → Input Map) для действий: ui_left, ui_right, ui_up, ui_down, click, jump, dash и т. п. Это упростит поддержку разных устройств.
Примечание: код из этой статьи можно поместить в файл Player.gd, прикреплённый к узлу CharacterBody2D.
Перемещение игрока с клавиатуры
Ниже минимальный пример перемещения по стрелкам или WASD. Он получает направление ввода, нормализует вектор, умножает на скорость и вызывает move_and_collide.
extends CharacterBody2D
@export var speed: float = 300.0
func _physics_process(delta: float) -> void:
var input_dir := Vector2.ZERO
if Input.is_action_pressed("ui_left"):
input_dir.x -= 1
if Input.is_action_pressed("ui_right"):
input_dir.x += 1
if Input.is_action_pressed("ui_up"):
input_dir.y -= 1
if Input.is_action_pressed("ui_down"):
input_dir.y += 1
# Нормализация сохраняет равную скорость по диагонали
if input_dir != Vector2.ZERO:
velocity = input_dir.normalized() * speed
else:
velocity = Vector2.ZERO
move_and_collide(velocity * delta)Пояснения:
- velocity — свойство CharacterBody2D (в Godot 4) для хранения скорости. Если вы используете кастомное имя, убедитесь, что его объявили.
- move_and_collide пытается переместить тело и вернёт информацию о столкновении.
- Умножение на delta обеспечивает независимость от FPS.
Добавление поворота в сторону движения
Чтобы персонаж поворачивался в направлении движения (например, танк или корабль), обновляйте rotation на основе горизонтальной силы вращения и входа.
extends CharacterBody2D
@export var speed: float = 400.0
@export var rotation_speed: float = 3.0 # радианы в секунду
var rotation_direction: float = 0.0
func get_input() -> void:
rotation_direction = Input.get_action_strength("ui_right") - Input.get_action_strength("ui_left")
velocity = transform.x * (Input.get_action_strength("ui_up") - Input.get_action_strength("ui_down")) * speed
func _physics_process(delta: float) -> void:
get_input()
rotation += rotation_direction * rotation_speed * delta
move_and_slide()Пояснения:
- transform.x — локальная ось X узла; умножение даёт вектор направления в мировых координатах.
- rotation изменяется плавно в зависимости от rotation_speed.
- move_and_slide удобен, если вы хотите учитывать скольжение по поверхностям и автоматическое выравнивание по нормали.
Перемещение и поворот по мыши
Два распространённых поведения: 1) клик — движение к позиции курсора; 2) поворот лицом к курсору.
Пример: движение к позиции клика мыши.
extends CharacterBody2D
@export var speed: float = 300.0
var target_position: Vector2 = Vector2.ZERO
var moving: bool = false
func _input(event):
if event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_LEFT and event.pressed:
target_position = get_global_mouse_position()
moving = true
func _physics_process(delta: float) -> void:
if moving:
var dir := (target_position - global_position)
if dir.length() < 2.0:
moving = false
velocity = Vector2.ZERO
else:
velocity = dir.normalized() * speed
move_and_collide(velocity * delta)Поворот лицом к курсору:
extends CharacterBody2D
func _physics_process(delta: float) -> void:
var mouse_position := get_global_mouse_position()
var target_angle := (mouse_position - global_position).angle()
rotation = target_angleСовет: если хотите плавный поворот, используйте lerp_angle или move_toward в угловой области.
Дополнительные механики движения
Ниже — краткие шаблоны и идеи для расширения базового управления.
Прыжок
Прыжок требует физики по вертикали и силы гравитации. В 2D-платформере добавляют gravity, is_on_floor() проверку и начальную вертикальную скорость при прыжке.
Ключевые пункты:
- Добавьте флаг
is_jumpingи силу прыжкаjump_force. - Проверяйте
is_on_floor()перед применением прыжка. - Используйте
deltaдля интеграции гравитации.
Рывок (Dash)
Рывок — короткий всплеск скорости. Имейте cooldown и время действия.
- Создайте
dash_speed,dash_time,dash_cooldown. - Во время рывка игнорируйте обычную обработку скорости.
Скольжение по стене и лазанье
Эти механики требуют проверки столкновений по сторонам (используйте RayCast2D или контактные данные столкновений).
- Wall slide: при соприкосновении со стеной уменьшайте падающую скорость.
- Wall jump: при нажатии прыжка рядом со стеной давайте направленную отталкивающую скорость.
Платформерная физика (ускорение, трение)
Реализуйте ускорение и трение, чтобы движение выглядело естественно:
- velocity = lerp(velocity, target_velocity, accel * delta)
- Применяйте фрикцию, когда нет ввода
Лучшие практики
- Разделяйте обязанности: один скрипт — ввод, другой — движение, третий — анимация.
- Всегда умножайте на delta для независимости от FPS.
- Ограничивайте максимальную скорость и проверяйте столкновения.
- Настраивайте слои столкновений и mask для исключения нежелательных взаимодействий.
- Добавляйте визуальную и звуковую отдачу (частицы, шаги, звуки рывка).
Альтернативные подходы и сравнение
- CharacterBody2D против KinematicBody2D: в Godot 4 CharacterBody2D заменил KinematicBody2D; если вы мигрируете с Godot 3, учтите различия в API.
- move_and_collide: удобен для простых перемещений с детектированием первого столкновения.
- move_and_slide: удобен для платформеров и скольжения по поверхностям.
- Использовать PhysicsDirectBodyState (в _integrate_forces) — для низкоуровневой физики и тонкой настройки.
Когда не стоит использовать CharacterBody2D:
- Если вам нужна полностью физически-правильная симуляция с силами и импульсами, рассмотрите RigidBody2D.
- Для сетевых игр с авторитетной физикой сервера понадобятся дополнительные корректировки и предсказание позиций.
Отладка и когда это ломается
- Проверяйте, не оставлены ли включёнными CollisionShape2D в режиме disabled.
- Если персонаж «застревает», проверьте размеры формы и слои столкновений.
- При рывках или очень высокой скорости используйте continuous collision detection или уменьшайте шаг перемещения.
Ментальные модели и эвристики
- Разделяй и властвуй: обработка ввода и физики — отдельные узлы/функции.
- Всегда думайте в векторах: направление + скорость = движение.
- Используйте state machine для состояний игрока: idle, run, jump, dash, wall_slide.
Чеклисты по ролям
Разработчик:
- InputMap настроен
- CharacterBody2D и CollisionShape2D настроены
- Базовый код перемещения добавлен
- Тесты на столкновения пройдены
Дизайнер:
- Ощущение скорости соответствует геймплею
- Анимации для бега/прыжка/рывка есть
- Эффекты и звуки настроены
QA:
- Поведение при различных FPS стабильное
- Нет туннели застревания в коллайдерах
- Платформы и лестницы работают корректно
Критерии приёмки
- Персонаж перемещается по вводу клавиатуры и мыши.
- Скорость одинакова на разных частотах кадров (delta учтён).
- Столкновения корректны: игрок не проходит сквозь стены и не уходит под тайл.
- Поворот/ориентация соответствует ожидаемому поведению (по направлению движения или курсору).
- Дополнительные механики (прыжок, рывок) работают с корректными таймингами и cooldown.
Мини-методология для внедрения механики движения
- Прототип: реализуйте минимальное перемещение.
- Инструмент: подключите InputMap и отладьте на клавиатуре.
- Полировка: добавьте плавность (interpolation), анимации и звуки.
- Тестирование: проверяйте на разных разрешениях и частотах кадров.
- Рефакторинг: вынесите ввод и физику в отдельные модули.
Тесты и приёмочные сценарии
- ТС1: Нажатие и удержание вправо должно давать постоянную скорость без рывков.
- ТС2: Движение по диагонали не должно превосходить модуля скорости (нормализация работает).
- ТС3: При быстрой смене направления персонаж не должен застревать в коллайдере.
- ТС4: Рывок работает только при условии завершения cooldown.
Короткий справочник (cheat sheet)
- Input.is_action_pressed(“action”) — проверка удержания.
- Input.is_action_just_pressed(“action”) — однократное нажатие.
- move_and_collide(velocity * delta) — перемещение с проверкой столкновения.
- move_and_slide() — удобен для платформеров и автоматического скольжения.
- transform.x / transform.y — локальные оси узла в мировых координатах.
Глоссарий (1 строка на термин)
- CharacterBody2D — узел для управления персонажем в Godot 4 с поддержкой функций перемещения.
- move_and_collide — метод перемещения, возвращающий контакт при столкновении.
- move_and_slide — метод перемещения, удобный для платформерной логики.
- delta — время между кадрами; используется для нормализации движения.
Совместимость и миграция
- Godot 3 → Godot 4: KinematicBody2D заменён CharacterBody2D; API методов и имена свойств могли измениться. При миграции проверьте вызовы move_and_slide и обработку velocity.
Краткий итог
Плавное и отзывчивое перемещение игрока — сочетание правильной архитектуры, работы с delta, векторной математики и тщательного тестирования. Начните с простого прототипа, затем добавляйте слои поведения (прыжки, рывки, взаимодействие со стенами) и отделяйте ввод от физики.
FAQ
Q: Теперь мой игрок двигается — как проверить столкновения?
A: Используйте встроенные методы (move_and_collide или move_and_slide) и отладочный режим коллайдеров (Visible Collision Shapes) в Godot. Также выводите в консоль результат вызова move_and_collide для отладки.
Q: Похож ли процесс в Unity?
A: В Unity логика похожа концептуально, но реализация на C# и трёхмерное пространство. API и физика отличаются, поэтому прямой перенос кода невозможен.
Q: А как в Python Arcade?
A: Arcade — 2D-библиотека на Python; концепции направления, скорости и коллизий аналогичны, но API и рендеринг отличаются. После освоения Godot, базовые идеи окажутся полезными.
Резюме: начните с CharacterBody2D, настройте InputMap, реализуйте базовое движение с учётом delta, затем добавляйте поворот, прыжки, рывки и визуальную обратную связь. Следуйте чеклистам и критериям приёмки для стабильного результата.
Похожие материалы
WireGuard на Windows: установка и настройка VPN
Как создать игру в Tabletop Simulator
Скачать видео из Twitter — пошагово
Установка Ubuntu через Mini ISO
CAN-шина с MCP2515 и Arduino: сборка и код