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

Система здоровья и урона в Godot: руководство с примерами

7 min read Game Dev Обновлено 05 Jan 2026
Система здоровья и урона в Godot
Система здоровья и урона в Godot

аркадная игра с индикатором здоровья и счётом

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

В этой статье вы найдёте рабочие примеры GDScript, архитектурные рекомендации и практические приёмы для расширения механики здоровья — от простого уменьшения HP до временной неуязвимости и регенерации.

Что вы получите

  • Основной пример: игрок, движение и UI-полоса здоровья.
  • Обработку урона при выходе за границы экрана.
  • Реализацию подборок здоровья и таймера неуязвимости.
  • Советы по организации кода, тестам и балансировке.
  • Чек-листы для разработчика, дизайнера и QA.

Установка проекта и структура

Создайте сцену игрока и HUD в Godot. Для 2D-игры подойдёт KinematicBody2D (Godot 3.x) или CharacterBody2D (Godot 4.x). Внутри добавьте CollisionShape2D и Sprite.

Оригинальный минимальный скрипт движения (сохраните как Player.gd):

# Player.gd  
extends KinematicBody2D  
  
const SPEED = 200  
  
var velocity = Vector2.ZERO  
var health = 100  
  
func _physics_process(delta):  
    velocity.x = 0  
    velocity.y = 0  
  
    if Input.is_action_pressed("ui_right"):  
        velocity.x += SPEED  
    elif Input.is_action_pressed("ui_left"):  
        velocity.x -= SPEED  
  
    if Input.is_action_pressed("ui_down"):  
        velocity.y += SPEED  
    elif Input.is_action_pressed("ui_up"):  
        velocity.y -= SPEED  
  
    move_and_collide(velocity * delta)

Примечание: для Godot 4 замените KinematicBody2D на CharacterBody2D и move_and_collide на move_and_slide или соответствующий API.

Дизайн UI полосы здоровья

Godot имеет контрол TextureProgress, который удобно использовать как индикатор здоровья. Создайте CanvasLayer для HUD и добавьте TextureProgress. У TextureProgress есть две текстуры: Under (фон) и Over (заполненная часть).

Простой HUD-скрипт, который читает свойство health у игрока и обновляет полосу:

# HUD.gd  
extends CanvasLayer  
  
onready var healthBar := $TextureProgress  
  
func _ready():  
    update_health_bar()  
  
func update_health_bar():  
    var hb = get_parent().get_node("KinematicBody2D")  
    healthBar.value = hb.health

UX-совет: выставьте свойство max_value у TextureProgress равным максимуму HP (например 100), используйте плавную анимацию заполнения и подсветку при критическом здоровье.

простая сцена с игровым персонажем

Урон при выходе за границы экрана

Ниже пример логики, где игрок получает урон, если уходит за пределы экрана. Этот код расширяет предыдущий Player.gd.

# player.gd  
extends KinematicBody2D  
  
const SPEED = 200  
const DAMAGE_AMOUNT = 0.1  
  
var velocity = Vector2.ZERO  
var health = 100  
  
# Screen boundaries  
var screen_size  
var margin = 20  
  
func _ready():  
    screen_size = get_viewport_rect().size  
  
func _physics_process(delta):  
    # ... (existing movement code)  
    move_and_collide(velocity * delta)  
  
    var c1 = position.x < -margin  
    var c2 = position.x > screen_size.x + margin  
    var c3 = position.y < -margin  
    var c4 = position.y > screen_size.y + margin  
  
    # Check if the player is outside the screen boundaries  
    if c1 or c2 or c3 or c4:  
        take_damage_on_screen_exit()  
  
func take_damage_on_screen_exit():  
    health -= DAMAGE_AMOUNT  
    if health <= 0:  
        health = 0  
        # Game over logic here     
      
    update_health_ui()

Добавьте функцию update_health_ui(), чтобы уведомлять HUD о изменении.

# Player.gd  
extends KinematicBody2D  
  
# ... (other code)  
  
func update_health_ui():  
    var hud = get_parent().get_node("HUD")  
    if hud:  
        hud.update_health_bar()

Важно: DAMAGE_AMOUNT в примере очень мал (0.1) — это иллюстрация. В реальной игре используйте целочисленные значения или величины, масштабированные по времени (health -= damage * delta), если урон наносится за секунду.

сцена Godot с персонажем и полосой здоровья

Улучшение архитектуры: разделение ответственности

Хорошая практика — отделять механику здоровья от логики движения. Для этого вынесите систему здоровья в отдельный скрипт или ноду (например, Health.gd) и используйте сигналы для уведомлений:

  • Health нода: хранит current_health, max_health, методы take_damage(amount), heal(amount), set_invincible(time).
  • Player подписывается на сигналы health_changed и died.
  • HUD подписывается на health_changed, чтобы обновлять UI.

Пример Health.gd:

# Health.gd  
extends Node  
  
signal health_changed(value)  
signal died()  
  
export var max_health := 100  
var current_health := max_health  
var invincible := false  
var inv_timer := null  
  
func _ready():  
    current_health = max_health  
  
func take_damage(amount):  
    if invincible:  
        return  
    current_health = max(0, current_health - amount)  
    emit_signal("health_changed", current_health)  
    if current_health == 0:  
        emit_signal("died")
  
func heal(amount):  
    current_health = min(max_health, current_health + amount)  
    emit_signal("health_changed", current_health)  
  
func set_invincible(duration):  
    invincible = true  
    if inv_timer:  
        inv_timer.stop()  
    else:  
        inv_timer = Timer.new()  
        add_child(inv_timer)  
    inv_timer.wait_time = duration  
    inv_timer.one_shot = true  
    inv_timer.start()  
    inv_timer.connect("timeout", Callable(self, "_on_inv_timer_timeout"))
  
func _on_inv_timer_timeout():  
    invincible = false

Преимущества: код чище, легко тестируется, HUD и игровые объекты не зависят напрямую друг от друга.

Примеры дополнительных функций

Ниже — примеры часто добавляемых механик.

Подборки здоровья (Health pickup)

Сцена: Area2D + CollisionShape2D + Sprite. Скрипт реагирует на signal body_entered и увеличивает здоровье игрока.

# HealthPickup.gd  
extends Area2D  
  
export var heal_amount := 20  
  
func _ready():  
    connect("body_entered", self, "_on_body_entered")  
  
func _on_body_entered(body):  
    if body.has_method("heal"):  
        body.heal(heal_amount)  
        queue_free()

Если вы используете Health-нод как дочернюю ноду игрока, вызывайте body.get_node(“Health”).heal(heal_amount) или используйте интерфейсные методы.

Временная неуязвимость (Invincibility power-up)

При подборе включайте invincibility для заданного времени и добавляйте визуальный фидбек (вспышки, полупрозрачность, частицы).

# при подборе power-up  
player.get_node("Health").set_invincible(3.0)  # 3 секунды

Регенерация здоровья

Регенерация по таймеру: если игрок не получал урон N секунд, запускается таймер, который прибавляет X HP каждые T секунд.

Реализация: храните last_damage_time и проверяйте в _process(delta). Регенерация должна быть ограничена и сбрасываться при получении урона.

Варианты обнаружения столкновений

  • При контакте с врагом — Area2D с сигналом body_entered.
  • Урон при ударе — прямое обращение enemy.attack(player).
  • Урон при движении вне зоны — проверка позиции (как в примере с границами).

Выбор зависит от игрового дизайна: Area2D удобен для триггеров, а прямые вызовы подходят для явно направленных атак.

Балансировка и методология (мини-метод)

  1. Установите базовый максимум HP (например, 100) и минимальный размер урона (например, 1 единица).
  2. Смоделируйте сценарии: одиночный удар, серия ударов, уровни сложности.
  3. Подберите скорость регенерации и время неуязвимости с учётом желаемой сложности.
  4. Тестируйте: проигрывайте 100+ коротких сессий, фиксируйте ощущение сложности и подгоняйте числа.

Критерий успеха: игрок должен иметь шанс при грамотной игре, но ошибки должны ощущаться болезненно.

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

  • Игрок получает урон при пересечении границы экрана и HP уменьшается ожидаемо.
  • HUD обновляет полосу здоровья сразу после изменения HP.
  • Подборка здоровья увеличивает HP, но не превышает max_health.
  • Power-up неуязвимости блокирует урон на указанное время и затем снимается.
  • При достижении 0 HP генерируется сигнал died или вызывается сцена “Game Over”.

Технические тесты:

  • Проверить, что Health.gd эмитит health_changed на каждое изменение.
  • Проверить, что таймер invincible очищается и не остаётся висящих ссылок.

Совместимость и перенос между версиями Godot

  • Godot 3.x: используйте KinematicBody2D, move_and_collide или move_and_slide.
  • Godot 4.x: KinematicBody2D заменён на CharacterBody2D; некоторые методы движения и сигнатуры изменились. API таймеров и сигналы в целом схожи, но проверьте имена нод и методы движения.

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

Отладка и производительность

  • Избегайте частого поиска нод в _process/_physics_process (используйте onready переменные).
  • Для большого количества врагов пользуйтесь Area2D с группами (groups) и сигналами, чтобы централизовать обработку урона.
  • Профилируйте сцену, если много частиц при попаданиях — частицы можно отключать в низких настройках графики.

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

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

  • Вынесена логика здоровья в отдельную ноду/скрипт.
  • HUD подписан на изменения здоровья через сигнал.
  • Реализована защита от отрицательного HP и переполнения.
  • Покрыты основные тест-кейсы.

Дизайнер геймплея:

  • Значения max_health, damage, regen и durations настроены под желаемую сложность.
  • Добавлены визуальные/аудио-индикаторы для урона и восстановления.

QA:

  • Проверена работа power-up’ов и подборок на всех уровнях.
  • Убедились, что при достижении 0 HP срабатывает Game Over.

Когда это не сработает / ограничения

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

Рекомендации по безопасности и сохранности данных

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

Примеры тестов автоматизации (простые приемочные сценарии)

  • Unit: при вызове take_damage(30) у Health текущий HP уменьшается на 30 и эмитится health_changed.
  • Integration: при заходе в Area2D с HealthPickup игрок получает указанное значение здоровья и предмет удаляется.

Рекомендации по визуальной и аудио обратной связи

  • Пульсация полосы здоровья или изменение цвета при критическом уровне (<25%).
  • Короткий звук при получении урона и другой звук при подборе аптечки.
  • Эффекты экрана: шейк камеры при сильном ударе, частицы при подборе.

Быстрые шаблоны и сниппеты

  • Проверка на invincibility перед нанесением урона — всегда делайте.
  • Используйте export-переменные для параметров (max_health, damage_amount) — удобно настраивать из инспектора.

Дерево принятия решений (Mermaid)

flowchart TD
  A[Игрок получил событие урона?] -->|Нет| Z[Ничего не делать]
  A -->|Да| B{Игрок неуязвим?}
  B -->|Да| Z
  B -->|Нет| C[Вычесть HP]
  C --> D{HP <= 0?}
  D -->|Да| E[Сигнал died / Game Over]
  D -->|Нет| F[Emит health_changed]

Сводка и рекомендации

Интеграция системы здоровья делает игру более глубокой и стратегичной. Вынесите состояние здоровья в отдельную ноду, используйте сигналы для связи с HUD и другими системами, реализуйте подборки и power-up’ы через Area2D и таймеры. Тестируйте все сценарии и проверяйте совместимость при миграции между версиями Godot.

Ключевые шаги для быстрой реализации:

  1. Создайте Health ноду с take_damage/heal и сигналами.
  2. Подключите HUD к сигналам health_changed.
  3. Реализуйте подборки и временную неуязвимость через Area2D и Timer.

Важно: для сетевых игр состояние HP должно контролироваться сервером.

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

  • Разделяйте логику здоровья и UI.
  • Используйте сигналы вместо частых get_node вызовов.
  • Планируйте визуальный и звуковой фидбек для восприятия урона.
  • Тестируйте и балансируйте значения HP, урона и регена.

Важно: адаптируйте значения урона и регенерации под ваш жанр и целевую аудиторию — аркада, платформер или roguelike имеют разные ожидания по сложности.

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

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

RDP: полный гид по настройке и безопасности
Инфраструктура

RDP: полный гид по настройке и безопасности

Android как клавиатура и трекпад для Windows
Гайды

Android как клавиатура и трекпад для Windows

Советы и приёмы для работы с PDF
Документы

Советы и приёмы для работы с PDF

Calibration в Lightroom Classic: как и когда использовать
Фото

Calibration в Lightroom Classic: как и когда использовать

Отключить Siri Suggestions на iPhone
iOS

Отключить Siri Suggestions на iPhone

Рисование таблиц в Microsoft Word — руководство
Office

Рисование таблиц в Microsoft Word — руководство