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

Узнай, как реализовать механизм забора здоровья в Unity и улучшить геймплей

В большинстве игровых жанров, особенно в RPG и экшенах, возможность «забирать» здоровье у противника — это важный элемент геймплея. Это может давать персонажу дополнительные очки, усиление, а иногда даже спасать от гибели. В этой статье мы разберём, как реализовать такой механизм в Unity, какие паттерны стоит использовать, а также рассмотрим примеры из популярных игр, таких как God of War Ragnarok и Assassin’s Creed: Shadows.

Почему «забирать» здоровье важно?

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

Основные подходы к реализации

Система «damage over time» (DoT) + восстановление

Самый прямой способ: при попадании в противника, он получает урон и одновременно теряет часть своего здоровья, которое игрок получает. В Unity это можно реализовать через Physics.Raycast и OnTriggerEnter2D.

public class EnemyHealth : MonoBehaviour
{
 public int maxHealth = 100;
 public int currentHealth;

 void Start => currentHealth = maxHealth;

 public void TakeDamage(int dmg, PlayerHealth player)
 {

 currentHealth -= dmg;
 player.GainHealth(dmg); // игрок забирает часть урона
 if (currentHealth <= 0) Die;
 }
 void Die { Destroy(gameObject); }
}

В примере выше урон — dmg, а игрок получает тот же объём здоровья. Можно добавить коэффициент, чтобы не передавать всё.

Алгоритм «lifesteal»

Лайфстайл (или Lifesteal) — это классический способ в RPG и MOBA. Выражается в проценте от нанесённого урона, который возвращается игроку.

public class Lifesteal : MonoBehaviour
{
 public float lifestealPercent = 0.2f; // 20%

 public void ApplyDamage(Enemy enemy, int dmg, PlayerHealth player)
 {
 enemy.TakeDamage(dmg);
 int heal = Mathf.FloorToInt(dmg * lifestealPercent);
 player.GainHealth(heal);
 }}

Событийная система (UnityEvent)

В тех случаях, когда хочется избежать прямой ссылки между скриптами, лучше использовать событийный паттерн. В Unity это реализуется через UnityEvent или Action.

public class Enemy : MonoBehaviour
{
 public event Action OnDamageTaken;

 public void TakeDamage(int dmg)
 {
 currentHealth -= dmg;
 OnDamageTaken?.Invoke(dmg);
 if (currentHealth <= 0) Die;
 }
}

А в скрипте игрока:

public class PlayerHealth : MonoBehaviour
{
 void Awake
 {
 Enemy enemy = FindObjectOfType;
 enemy.OnDamageTaken += HealFromEnemy;
 }

 void HealFromEnemy(int dmg)
 {
 GainHealth(dmg);
 }
}

Визуальная и аудио обратная связь

Чтобы игрок ощущал эффект, важно добавить визуальные и звуковые сигналы. В Unity можно использовать OnGUI, Camera.main.WorldToScreenPoint и AudioSource.PlayClipAtPoint для звука.

void OnGUI
{
 Vector3 screenPos = Camera.main.WorldToScreenPoint(transform.position);
 Rect rect = new Rect(screenPos.x ― 50, Screen.height ― screenPos.y — 10, 100, 10);
 GUI.Box(rect, $"{currentHealth}/{maxHealth}");
}

Практический пример: Unity 3.5+ (с использованием Raycast)

Ниже приведён минимальный скрипт, который реализует базовый «lifesteal» при клике по врагу.

using UnityEngine;
using UnityEngine.Events;

public class PlayerAttack : MonoBehaviour
{ public LayerMask enemyLayer;
 public float attackRange = 2f;
 public int baseDamage = 15;
 public PlayerHealth playerHealth;

 void Update
 {
 if (Input.GetMouseButtonDown(0)) Attack;
 }
 void Attack
 {
 RaycastHit hit;
 if (Physics.Raycast(transform.position, transform.forward, out hit, attackRange, enemyLayer))
 {
 EnemyHealth enemy = hit.collider.GetComponent<EnemyHealth>;
 if (enemy != null)
 {
 enemy.TakeDamage(baseDamage, playerHealth);
 } }
 }
}

Примеры из популярных игр

God of War Ragnarok

В этой игре «забирать здоровье» реализовано через «черные камни» и «кристаллы» после убийства врагов. Камни скапливаются в инвентаре и могут использоваться для регенерации HP. Кроме того, некоторые снаряжения (например, Поясные щитки Гиптумадра) повышают шанс, что враг оставит камень здоровья.

Assassin’s Creed: Shadows

В игре предложена настройка HUD, где можно отключить полоски здоровья и имена над врагами. Для реализации подобной настройки в Unity можно добавить ScriptableObject с настройками UI и переключать их в редакторе.

Творческие идеи для вашего проекта

  • «Кровавый дождь» – при убийстве врага игрок получает «кровавый дождь», который периодически отнимает здоровье от всех врагов в радиусе.
  • «Бешеный яд» – после нанесения урона игроку от врагов появляется временная шкала, от которой он может «взять» здоровье, но при этом будет получать урон.
  • «Кровавая тень» – игрок может копировать здоровье врага, но при этом его собственные силы уменьшаются.

Тестирование и балансировка

При создании механизма «забирать здоровье» важно учесть следующее:

  1. Проверка границ – игрок не должен переполнить свой HP выше максимального.
  2. Нормализация урона – убедитесь, что вражеский урон и «lifesteal» находятся в одном диапазоне.
  3. Отладка – используйте Debug.Log для отслеживания событий.
  4. Пользовательский интерфейс – убедитесь, что здоровье корректно отображается как у врага, так и у игрока.

«Забирать здоровье» от врагов — это мощный инструмент, который добавляет глубину и стратегию в ваш игровой проект. С помощью описанных выше методов, вы можете легко интегрировать этот функционал в Unity, используя как простые скрипты, так и более продвинутые паттерны событий. Не забывайте о визуальной и аудио обратной связи, чтобы игрок чувствовал каждое действие. Удачной разработки!