Гид по технологиям

Обнаружение столкновений в Godot 4

6 min read Разработка игр Обновлено 31 Dec 2025
Обнаружение столкновений в Godot 4 — руководство
Обнаружение столкновений в Godot 4 — руководство

Игровой мир с платформами и персонажем

Введение

Обнаружение столкновений (collision detection) — это процесс определения пересечения физических примитивов в игровом мире. Оно отвечает за то, когда персонаж наступает на платформу, попадает на снаряд или отталкивается от стены. Правильно настроенное обнаружение делает механику игры предсказуемой и приятной для игрока.

В Godot 4 есть готовые ноды и API для физики, которые позволяют сочетать простые и эффективные формулы с гибкими настройками слоёв и масок столкновений. Этот материал подходит для 2D-платформера, но многие принципы применимы в 3D.

Что нужно подготовить

  • Godot 4 (рекомендуется последняя стабильная ветка).
  • Новая сцена с узлом CharacterBody2D в качестве корня.
  • Sprite2D (или AnimatedSprite2D) для визуала игрока.
  • StaticBody2D для платформ и препятствий.

Код из статьи свободен под MIT (указано в исходном материале).

Быстрый пример движения игрока

Ниже — упрощённый пример обработки ввода и движения с использованием move_and_collide. Этот пример демонстрационный; для платформера добавьте гравитацию и прыжок.

extends CharacterBody2D

var speed := 300

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

    velocity = input_dir.normalized() * speed
    var collision = move_and_collide(velocity * delta)
    if collision:
        print("collided with: ", collision.get_collider())

Важно: move_and_collide возвращает объект столкновения при пересечении; можно читать нормали, позицию касания и ссылку на коллайдер.

Простая сцена Godot с игроком и платформой

Типы форм столкновений и когда их использовать

Godot предоставляет несколько базовых форм в 2D. Правильный выбор влияет на производительность и поведение столкновений.

Круг (CircleShape2D)

  • Лучшее применение: круглые персонажи, шарики, объекты, где важна радиальная симметрия.
  • Плюсы: дешёвая проверка, плавные отскоки без углов.
  • Минусы: плохо подходит для коробочных форм.

Пример создания в коде:

var collision_shape := CollisionShape2D.new()
var circle_shape := CircleShape2D.new()
circle_shape.radius = 32
collision_shape.shape = circle_shape
add_child(collision_shape)

Прямоугольник (RectangleShape2D)

  • Применение: платформеры, враги с прямоугольным хитбоксом, объекты уровня.
  • Плюсы: простая геометрия, хорошо моделирует боковые столкновения и земля.
  • Минусы: углы могут застревать в узких проходах.
var collision_shape := CollisionShape2D.new()
var rect_shape := RectangleShape2D.new()
rect_shape.extents = Vector2(32, 64)
collision_shape.shape = rect_shape
add_child(collision_shape)

Выпуклый многоугольник (ConvexPolygonShape2D)

  • Применение: сложные стабильно выпуклые формы для точного соответствия силуэту.
  • Плюсы: лучшее соответствие внешнему контуру, стабильная физика.
  • Минусы: дороже в расчётах, нельзя задавать вогнутые контуры.
var collision_shape := CollisionShape2D.new()
var polygon_shape := ConvexPolygonShape2D.new()
polygon_shape.set_points([Vector2(-32, -64), Vector2(32, -64), Vector2(0, 64)])
collision_shape.shape = polygon_shape
add_child(collision_shape)

Совет: комбинируйте несколько простых форм вместо одной сложной — это часто проще для поддержки и быстрее по производительности.

Обнаружение столкновений в процессе физики

Выше мы пример показал move_and_collide. Ещё один распространённый способ — move_and_slide (или аналогичная логика у CharacterBody2D) для характерного поведения персонажа при скольжении по поверхностям.

Пример с обработкой столкновения:

func _physics_process(delta: float) -> void:
    # ... ввод и вычисление velocity
    var collision = move_and_collide(velocity * delta)
    if collision:
        var other = collision.get_collider()
        if other:
            print("Столкновение с:", other.name)
            # можно читать collision.get_position(), get_normal() и другие поля

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

Два объекта сталкиваются в Godot, визуализация столкновения

Сигналы столкновений и группы

Сигналы позволяют реагировать на контактные события, не проверяя всё вручную.

body_entered и body_exited

Эти сигналы отправляют узел, когда другой PhysicsBody2D входит или выходит из зоны столкновения (например, Area2D или CollisionObject2D). Это удобно для триггеров, коллекционных предметов и зон событий.

Пример реакции на коллекционный предмет:

func _ready() -> void:
    connect("body_entered", Callable(self, "_on_body_entered"))

func _on_body_entered(body: Node) -> void:
    if body.is_in_group("collectible"):
        play_collectible_sound()
        body.queue_free()

Заметьте: используйте группы для логического разделения типов объектов (collectible, enemy, platform).

Слои и маски столкновений

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

Пример сценария:

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

Реализация (псевдокод в GDScript):

# В скрипте врага
func _ready() -> void:
    # отключить маску столкновения с другими врагами (слой 2)
    set_collision_mask_value(2, false)
    # включить столкновения с платформами (слой 3)
    set_collision_mask_value(3, true)

# В скрипте пули
func _ready() -> void:
    set_collision_mask_value(2, true) # пуля должна бить врагов
    set_collision_mask_value(3, false) # пуля не должна бить платформы

Хорошая практика: документируйте назначение слоёв в проекте (например, 1 — игрок, 2 — враги, 3 — платформа, 4 — пули).

Практические рекомендации и шаблоны

Используйте простые формы

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

Гибридный хитбокс

Комбинируйте несколько CollisionShape2D для игрока: один для земли, другой для боков и верхней части. Это даёт точный контроль столкновений для разных ситуаций (столкновение с платформой vs зацеп за угол).

Bounding boxes перед точной проверкой

Сначала проверяйте простую AABB-бокс проверку (get_global_transform().xform_rect() или area overlap), затем выполняйте точную физическую проверку. Это уменьшает число дорогих вычислений.

Частые оптимизации

  • Сократите количество активных физических тел.
  • Переводите неактивные объекты в статические или выключайте коллайдеры.
  • Используйте слои, чтобы исключить лишние пересечения.

Отладка и проверка коллизий

  • Включите «Visible Collision Shapes» в отладчике Godot — вы увидите все формы коллайдеров.
  • Печайте сведения о столкновении: нормали, позиции, имя коллайдера.
  • Тестируйте граничные случаи: очень высокие скорости (трассировка сквозь объекты), узкие проходы, последовательные столкновения.

Методика внедрения (мини-SOP)

  1. Создайте базовую сцену с CharacterBody2D и StaticBody2D платформ.
  2. Назначьте простые CollisionShape2D (прямоугольник/круг).
  3. Определите схемy слоёв и масок и задокументируйте их.
  4. Добавьте сигналы для предметов и зон.
  5. Протестируйте базовые столкновения в режиме отладки.
  6. Оптимизируйте формы и выключайте ненужные физические тела.

План тестирования и критерии приёмки

Критерии приёмки:

  • Игрок не проходит сквозь платформы при нормальных скоростях.
  • Коллекционные предметы удаляются и дают эффект при касании.
  • Пули попадают в врагов и не взаимодействуют с платформами.
  • Враги не сталкиваются друг с другом, если это запланировано.

Тесты принятия:

  • unit-тесты сценариев столкновений (при наличии тестовой инфраструктуры).
  • ручное тестирование в редакторе с включёнными видимыми коллайдерами.
  • стресс-тест: сотни объектов с выключенными физическими расчётами для неактивных.

Отказоустойчивость: когда подход может не сработать

  • Высокоскоростные объекты могут «пролетать» сквозь мелкие коллайдеры — для них используйте трассировку (raycast) или увеличивайте шаг проверки.
  • Сложные вогнутые формы: ConvexPolygon не подходит для вогнутых контуров — разделите форму на несколько выпуклых частей.
  • Большое число динамических тел: подумайте о переходе части логики в события/триггеры вместо физики.

Альтернативные подходы

  • Area2D + кастомная логика перекрытий для триггеров (когда не нужно физическое столкновение).
  • RayCast2D/ShapeCast2D для предиктивной проверки столкновений на большой скорости.
  • Использование пробной симуляции движения через kinematic queries, чтобы предсказывать столкновения до реального перемещения.

Чеклист разработчика перед релизом

  • Документированы слои столкновений проекта.
  • Включена отладочная визуализация и прогнана сессия тестов.
  • Комбинация форм оптимизирована для производительности.
  • Специальные случаи (прыжок через угол, скольжение по стене) протестированы.
  • Логика удаления/падения предметов не вызывает утечек памяти.

Процесс отладки: runbook

  1. Включить Visible Collision Shapes.
  2. Выполнить сценарий, где проявляется баг.
  3. Посмотреть, пересекаются ли формы или «пролетают» сквозь них.
  4. Если «пролёт» — добавить ShapeCast2D или raycasts; уменьшить timestep для проверки.
  5. Если неправильная реакция — проверить нормаль столкновения и порядок обновления velocity.

Ментальные модели и эвристики

  • Модель «слой-фильтр»: думайте про коллайдеры как про категории с разрешениями на взаимодействие.
  • Модель «первый-уровень/второй-уровень»: сначала грубая AABB-проверка, затем точная физическая проверка.
  • Эвристика производительности: простые формы для большого числа объектов, сложные формы только при необходимости.

Решающее дерево для выбора метода

flowchart TD
  A[Нужно физическое столкновение?] -->|Да| B{Движение контролируемо}
  A -->|Нет| Z[Использовать Area2D или события]
  B -->|Да| C{Высокая скорость объекта}
  B -->|Нет| D[Использовать move_and_collide/move_and_slide]
  C -->|Да| E[Добавить ShapeCast2D или RayCast2D]
  C -->|Нет| D
  D --> F[Выбрать форму: круг/прямоугольник/комбинация]
  F --> G[Назначить слои и маски]
  G --> H[Тест и отладка]

Короткий глоссарий

  • CollisionShape2D — контейнер для формы столкновения.
  • CollisionMask/Layer — битовый фильтр взаимодействий.
  • Area2D — зона перекрытия, часто используется для триггеров.
  • ShapeCast2D — инструмент для предиктивной трассировки формы.

Совместимость и советы по миграции

  • Если портируете проект из Godot 3, проверьте соответствие нод KinematicBody2D → CharacterBody2D и обновите вызовы методов движения.
  • Перепроверьте экспортированные сцены на предмет устаревших свойств коллайдеров и слоёв.

Заключение

Хорошо спроектированная система столкновений — это синергия правильного выбора форм, продуманной структуры слоёв/масок, сигналов и тестовой методики. Начните с простых форм, документируйте слои и постепенно добавляйте точность там, где это действительно необходимо. Правильная отладка и чеклист помогут избежать распространённых ошибок и обеспечить плавную, предсказуемую механику для игрока.

Ключевые ресурсы: оффлайн документация Godot (локальная справка в редакторе) и официальные туториалы по физике в Godot 4.

Поделиться: X/Twitter Facebook LinkedIn Telegram
Автор
Редакция

Похожие материалы

Как вести протокол собрания
Продуктивность

Как вести протокол собрания

VirtualTourist: советы путешественников и путеводители
Путешествия

VirtualTourist: советы путешественников и путеводители

Как смотреть несколько часовых поясов на iPhone
iPhone

Как смотреть несколько часовых поясов на iPhone

MacBook с закрытой крышкой: clamshell — настройка и советы
MacBook

MacBook с закрытой крышкой: clamshell — настройка и советы

Spike: почта как рабочее пространство
Продуктивность

Spike: почта как рабочее пространство

Google Календарь: расписание и организация семестра
Продуктивность

Google Календарь: расписание и организация семестра