В большинстве игровых жанров, особенно в 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 и переключать их в редакторе.
Творческие идеи для вашего проекта
- «Кровавый дождь» – при убийстве врага игрок получает «кровавый дождь», который периодически отнимает здоровье от всех врагов в радиусе.
- «Бешеный яд» – после нанесения урона игроку от врагов появляется временная шкала, от которой он может «взять» здоровье, но при этом будет получать урон.
- «Кровавая тень» – игрок может копировать здоровье врага, но при этом его собственные силы уменьшаются.
Тестирование и балансировка
При создании механизма «забирать здоровье» важно учесть следующее:
- Проверка границ – игрок не должен переполнить свой HP выше максимального.
- Нормализация урона – убедитесь, что вражеский урон и «lifesteal» находятся в одном диапазоне.
- Отладка – используйте
Debug.Logдля отслеживания событий. - Пользовательский интерфейс – убедитесь, что здоровье корректно отображается как у врага, так и у игрока.
«Забирать здоровье» от врагов — это мощный инструмент, который добавляет глубину и стратегию в ваш игровой проект. С помощью описанных выше методов, вы можете легко интегрировать этот функционал в Unity, используя как простые скрипты, так и более продвинутые паттерны событий. Не забывайте о визуальной и аудио обратной связи, чтобы игрок чувствовал каждое действие. Удачной разработки!