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

Усиления и коллекционные предметы в Godot: руководство по созданию

7 min read Game Dev Обновлено 11 Apr 2026
Усиления и коллекции в Godot
Усиления и коллекции в Godot

Человек играет в портативную консоль Nintendo Switch

Добавление усилений и коллекционных предметов в вашу игру на Godot делает геймплей более интересным и привлекательным. Усиления дают временные преимущества, а коллекции — награды, очки или доступ к бонусам.

Ниже вы найдёте подробные инструкции, примеры кода и практические советы по проектированию, тестированию и внедрению таких механик.

О чём эта статья

  • Простая реализация игрока и столкновений на 2D-сцене.
  • Как создать коллекционные предметы (монеты) и увеличить счёт.
  • Как сделать временные усиления с таймером.
  • Варианты реализации, тест-кейсы, чек-листы для дизайнеров, разработчиков и QA.

Важно: термины в одной строке:

  • Area2D — узел для областей столкновения, обычно используется для подбора предметов.
  • CollisionShape2D — форма столкновения (круг, прямоугольник и т. д.).
  • CharacterBody2D — персонаж с методами движения и столкновений.

Подготовка проекта Godot

Создайте 2D-проект в Godot и сцену с игроком. Простейшая сцена может выглядеть так:

  • Node2D (Root)
    • Player (CharacterBody2D)
      • Sprite2D
      • CollisionShape2D
    • Enemy (CharacterBody2D или RigidBody2D)
    • Collectibles (Node2D)
    • Powerups (Node2D)
    • UI (CanvasLayer)
      • Label

Пример простого скрипта движения игрока (Player.gd). Этот код обеспечивает движение со скоростью и нормализацию векторов, чтобы направление по диагонали не давало повышенной скорости:

extends CharacterBody2D

var speed = 200

func _physics_process(delta):
    var velocity = Vector2()

    if Input.is_action_pressed('ui_right'):
        velocity.x += 1

    if Input.is_action_pressed('ui_left'):
        velocity.x -= 1

    if Input.is_action_pressed('ui_down'):
        velocity.y += 1

    if Input.is_action_pressed('ui_up'):
        velocity.y -= 1

    velocity = velocity.normalized() * speed
    move_and_collide(velocity * delta)

Этот код даёт базовую механику перемещения. В боевом проекте замените move_and_collide на move_and_slide с дополнительной обработкой столкновений, если нужно.

Простая сцена с игроком и врагом

Создание коллекционных предметов (монеты)

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

  1. Создайте новую сцену с корнем Area2D.
  2. Добавьте Sprite2D и CollisionShape2D (круг).
  3. В родительской сцене разместите несколько экземпляров в узле Collectibles.

Сигнал Area2D — body_entered — срабатывает при входе тела (например, игрока).

Пример простейшей логики: удалять монету и увеличивать счёт. Вариант реализации может быть как в скрипте монеты, так и в скрипте игрока. Ниже — реализация через сигнал в сцене монеты (Coin.gd):

extends Area2D

export(int) var value = 20

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

func _on_body_entered(body):
    if body.name == "Player":
        # Предполагается, что у игрока есть свойство score
        if body.has_variable("score"):
            body.score += value
        queue_free()

Альтернативный подход: подписаться на сигнал в скрипте игрока. Это полезно, если логика сбора зависит от состояния игрока (например, множитель очков).

Пример: в Player.gd подписка на сигнал из коллекции:

func _ready():
    for coin in get_parent().get_node("Collectibles").get_children():
        coin.connect("body_entered", Callable(self, "_on_coin_collected"))

func _on_coin_collected(body):
    if body == self:
        score += 20

Советы:

  • Используйте пуллинг (ObjectPool) для частых спаунов, чтобы избежать частых вызовов queue_free()/instance().
  • Давайте разным типам коллекций разные значения value и разные спрайты.

Сцена с игроком и коллекционными предметами

Создание усилений (power-ups)

Усиления дают временное преимущество. В примере — усиление, которое в течение 10 секунд позволяет игроку уничтожать врагов при столкновении.

Подход 1 — через await и create_timer (как в исходнике). Подход 2 — через узел Timer. Второй даёт более гибкую управляемость (пауза, сброс, визуализация времени).

Пример через Timer: добавьте в сцену игрока узел Timer (name: PowerupTimer, one_shot: true). В Player.gd:

extends CharacterBody2D

var power_up_active = false
onready var powerup_timer = $PowerupTimer

func _ready():
    powerup_timer.one_shot = true
    powerup_timer.wait_time = 10.0
    powerup_timer.connect("timeout", Callable(self, "_on_powerup_timeout"))

func _on_powerups_body_entered(body):
    if body == self:
        power_up_active = true
        powerup_timer.start()
        body.queue_free() # удалить усиление

func _on_powerup_timeout():
    power_up_active = false

func _on_enemy_body_entered(enemy):
    if power_up_active:
        enemy.queue_free()
    else:
        # логика уничтожения игрока или уменьшения здоровья
        queue_free()

Преимущества Timer:

  • Можно видеть оставшееся время и отобразить прогресс в UI.
  • Можно приостановить игру и при необходимости приостановить таймер.

Советы по дизайну усилений:

  • Давайте простой визуальный эффект (например, аура) при активном усилении.
  • Отображайте оставшееся время в UI и давайте звуковой сигнал при истечении.
  • Рассмотрите уровни усиления (см. раздел расширений).

Отображение количества собранных предметов и UI

Для HUD используйте CanvasLayer, куда добавьте Label. Лучше держать логику UI в отдельном скрипте (HUD.gd) и подпитывать её сигналами от игрока.

Пример HUD.gd (Label обновляет счёт):

extends Label

func update_score(score):
    text = "Коллекции: %d" % score

В Player.gd просто вызывайте hud.update_score(score) после изменения очков.

Рекомендация: не вычисляйте UI внутри _physics_process каждый кадр без необходимости. Обновляйте только при изменении значения (событийно).

Метка счёта коллекционных предметов в сцене игрока

Дополнительные функции и идеи

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

Несколько уровней усилений

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

Комбинирующиеся усиления

Позвольте усилениям взаимодействовать. Например, скорость × урон. Для этого храните набор активных эффектов и вычисляйте итоговые множители.

Ограничения и кулдауны

Ограничьте частоту подбора одного типа усилений или добавьте кулдаун перед повторным применением. Это предотвращает балансные проблемы.

Разновидности коллекций

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

Сохранение прогресса

Если коллекции постоянные (например, собранные предметы в мире), храните прогресс в JSON или в Godot ConfigFile. При загрузке сцены восстанавливайте объекты или их статус.

Лучшие практики при реализации

  • Тестируйте баланс усилений на ранних итерациях.
  • Добавляйте визуальную и аудио отдачу при сборе предметов и активации усилений.
  • Обновляйте UI событиями, а не каждый кадр.
  • Обрабатывайте сетевые сценарии: синхронизируйте активации усилений и их окончание.
  • Правильно называйте узлы и сцены (удобно для поиска и отладки).

Методология разработки фичи (минимальная)

  1. Техническое задание: определить цели механики и критерии успеха.
  2. Прототип: реализовать простейшую логику в отдельной сцене.
  3. Игровая полировка: визуалы, звуки, фидбек.
  4. Баланс: playtest, корректировки по данным тестов.
  5. Интеграция: перенос в основную сцену, миграция данных.
  6. Тестирование: unit и QA тесты.
  7. Релиз и мониторинг.

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

  • Игрок может собирать монеты; значение счёта возрастает на ожидаемую величину.
  • Усиление активируется и длится ожидаемое время (±0.2 с).
  • Во время усиления столкновение с врагом уничтожает врага.
  • UI отображает текущее количество коллекций и оставшееся время усиления.
  • Нет утечек памяти при массовом спауне/удалении предметов.

Чек-листы по ролям

Дизайнер:

  • Определить типы усилений и их длительность.
  • Прописать визуальные и звуковые эффекты.
  • Утвердить баланс (очки, частота).

Разработчик:

  • Реализовать Area2D монет и усилений.
  • Добавить таймер/узел Timer для усилений.
  • Реализовать пуллинг для часто повторяющихся предметов.
  • Написать unit тесты для логики начисления очков.

QA:

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

Тест-кейсы и сценарии приёмки

  1. Сбор монеты
  • Предусловие: игрок рядом с монетой
  • Шаги: подойти к монете
  • Ожидание: монета исчезла, счёт +20, HUD обновлён.
  1. Усиление и столкновение с врагом
  • Предусловие: есть усиление в сцене
  • Шаги: подобрать усиление, столкнуться с врагом в течение 10 секунд
  • Ожидание: враг уничтожен, игрок жив.
  1. Таймер тест
  • Шаги: подобрать усиление, дождаться 10+ секунд, столкнуться с врагом
  • Ожидание: игрок получает повреждение/умирает по стандартной логике.
  1. Нагрузочный тест
  • Шаги: заспаунить 500 монет, подобрать их быстро
  • Ожидание: нет просадок памяти и фреймрейта ниже критического порога (зависит от проекта).

Модель принятия решений (Mermaid)

flowchart TD
  A[Нужно ли использовать Area2D?] -->|Да, подбор предметов| B[Использовать Area2D]
  A -->|Нет, физическое столкновение| C[Использовать CharacterBody2D / RigidBody2D]
  B --> D{Требуется таймер}
  D -->|Да| E[Использовать Timer или create_timer]
  D -->|Нет| F[Одноразовые эффекты]

Риски и меры смягчения

  • Риск: усиления ломают баланс игры. Митигейшн: вводите усиления постепенно и тестируйте на реальных сессиях.

  • Риск: большое количество экземпляров вызывает утечки или просадки. Митигейшн: используйте пуллинг и профилируйте память.

  • Риск: разночтение дизайна между командами. Митигейшн: поддерживайте единый документ с описанием эффектов и приоритетов.

Глоссарий в одну строку

  • Area2D: узел для областей, реагирующих на вхождение тел.
  • Timer: узел для отсчёта времени; удобен для длительных эффектов.
  • Pooling: повторное использование экземпляров вместо частых instance/queue_free.

Часто задаваемые вопросы

Какой способ лучше: подписываться на сигнал в монете или в игроке?

Оба подхода рабочие. Если логика зависит от состояния игрока — подписывайтесь в игроке. Если предмет самостоятелен — реализуйте обработчик в сцене предмета.

Как хранить прогресс собранных предметов между сессиями?

Экспортируйте данные в JSON или ConfigFile. Храните уникальные идентификаторы собранных предметов и при загрузке уровня скрывайте уже собранные.

Что лучше для сетевой игры?

Синхронизируйте активацию и окончание усилений через сервер. Решения на клиенте легко подделать.

Краткое резюме

  • Используйте Area2D для простых коллекций.
  • Для временных усилений применяйте Timer или create_timer.
  • Обновляйте UI событием, а не каждый кадр.
  • Добавьте тесты, чек-листы и профиль производительности при массовых спаунах.

Пишите аккуратно, тестируйте баланс и не забывайте про визуальную и аудио отдачу — они делают сбор предметов satisfying и увеличивают вовлечённость игроков.

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

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

CSS font-family: как менять шрифты на сайте
Frontend

CSS font-family: как менять шрифты на сайте

График амортизации кредита в Excel — пошагово
Финансы

График амортизации кредита в Excel — пошагово

Разгон Raspberry Pi 4 — безопасный пошаговый гид
Аппаратное обеспечение

Разгон Raspberry Pi 4 — безопасный пошаговый гид

Как запустить Windows 11 на Mac — варианты и советы
Mac

Как запустить Windows 11 на Mac — варианты и советы

Мошенничество с возвратом средств через техподдержку
Безопасность

Мошенничество с возвратом средств через техподдержку

Диагональная обрезка в Canva — как сделать эффектно
Дизайн

Диагональная обрезка в Canva — как сделать эффектно