Files
WhiteMan_Unity2D/Assets/02_Scripts/Combat/Health.cs
2026-05-19 10:51:56 +09:00

78 lines
3.2 KiB
C#

using System;
using UnityEngine;
// ============================================================================
// Health
// ----------------------------------------------------------------------------
// 순수한 HP 데이터 컴포넌트. 시각 효과/넉백/사망 처리는 일절 안 함.
// Enemy, Player 등 어떤 GameObject든 Health 컴포넌트만 추가하면 HP 관리 가능.
//
// 일반적 사용 흐름:
// 1) Enemy/Player가 IDamageable.TakeDamage 받음
// 2) 시각 효과(flash) + 넉백 처리
// 3) 마지막에 _health.TakeDamage(amount) 호출
// 4) Health가 HP 감소 + OnHealthChanged 이벤트 발화 → HP바 등 UI 자동 갱신
// 5) HP가 0 되면 OnDied 이벤트 발화 → Enemy가 HandleDeath()로 Destroy 등 처리
// ============================================================================
public class Health : MonoBehaviour
{
[SerializeField] private int _maxHealth = 30;
private int _currentHealth;
// ─── 읽기 전용 프로퍼티 ──────────────────────────────────────────────
public int MaxHealth => _maxHealth;
public int CurrentHealth => _currentHealth;
public float Ratio => _maxHealth > 0 ? (float)_currentHealth / _maxHealth : 0f;
public bool IsDead => _currentHealth <= 0;
// ─── 외부 구독용 이벤트 ──────────────────────────────────────────────
// OnHealthChanged: (current, max). HP바, 데미지 숫자 표시 등에 사용.
// OnDied: 사망 순간 1회만 발화. Enemy.HandleDeath에서 구독.
public event Action<int, int> OnHealthChanged;
public event Action OnDied;
private void Awake()
{
_currentHealth = _maxHealth;
}
// 데미지 적용. 양수 데미지만 받고, 이미 죽었으면 무시.
// OnDied는 "방금 죽은 순간"에만 발화 (previous > 0 && current == 0).
public void TakeDamage(int amount)
{
if (amount <= 0 || IsDead) return;
int previous = _currentHealth;
_currentHealth = Mathf.Max(_currentHealth - amount, 0);
OnHealthChanged?.Invoke(_currentHealth, _maxHealth);
if (_currentHealth <= 0 && previous > 0)
OnDied?.Invoke();
}
// 회복. 죽은 상태에서는 회복 안 됨 (부활 로직은 별도로 만들어야 함).
public void Heal(int amount)
{
if (amount <= 0 || IsDead) return;
_currentHealth = Mathf.Min(_currentHealth + amount, _maxHealth);
OnHealthChanged?.Invoke(_currentHealth, _maxHealth);
}
// 풀체력으로 리셋. 부활/재시작 시 사용.
public void ResetHealth()
{
_currentHealth = _maxHealth;
OnHealthChanged?.Invoke(_currentHealth, _maxHealth);
}
// 최대 HP 변경. fill=true면 현재 HP도 풀로 채우고, false면 새 max로 클램프만.
public void SetMaxHealth(int newMax, bool fill = true)
{
_maxHealth = Mathf.Max(newMax, 1);
if (fill) _currentHealth = _maxHealth;
else _currentHealth = Mathf.Min(_currentHealth, _maxHealth);
OnHealthChanged?.Invoke(_currentHealth, _maxHealth);
}
}