111 lines
3.7 KiB
C#
111 lines
3.7 KiB
C#
using UnityEngine;
|
|
using System;
|
|
using System.Collections;
|
|
|
|
public class PlayerHealth : MonoBehaviour, IDamageable
|
|
{
|
|
[Header("=== 참조 ===")]
|
|
[SerializeField] private Stats stats;
|
|
[SerializeField] private Animator animator;
|
|
[SerializeField] private PlayerAttack attackScript; // ⭐ 공격 상태 리셋을 위해 추가
|
|
|
|
public bool IsDead { get; private set; }
|
|
public bool isHit { get; private set; }
|
|
public bool isInvincible; // 대시 중 무적 플래그
|
|
|
|
// ⭐ 기존 OnHit 이벤트와 아래 OnHit() 함수의 이름 충돌을 피하기 위해 이름을 OnHitEvent로 변경함
|
|
public event Action OnHitEvent, OnDead;
|
|
public event Action<float, float> OnHealthChanged;
|
|
|
|
private float _currentHealth;
|
|
|
|
private IEnumerator Start()
|
|
{
|
|
yield return null;
|
|
|
|
if (stats != null)
|
|
{
|
|
_currentHealth = stats.MaxHealth;
|
|
OnHealthChanged?.Invoke(_currentHealth, stats.MaxHealth);
|
|
Debug.Log($"<color=cyan>[UI Sync]</color> 초기 체력 설정 완료: {_currentHealth}/{stats.MaxHealth}");
|
|
}
|
|
if (animator == null) animator = GetComponent<Animator>();
|
|
// 만약 인스펙터에서 할당 안했다면 자동으로 찾아옴
|
|
if (attackScript == null) attackScript = GetComponent<PlayerAttack>();
|
|
}
|
|
|
|
public void RefreshHealthUI()
|
|
{
|
|
if (stats != null)
|
|
{
|
|
_currentHealth = Mathf.Min(_currentHealth, stats.MaxHealth);
|
|
OnHealthChanged?.Invoke(_currentHealth, stats.MaxHealth);
|
|
}
|
|
}
|
|
|
|
public void TakeDamage(float amount)
|
|
{
|
|
if (isInvincible || IsDead) return;
|
|
|
|
_currentHealth = Mathf.Max(0, _currentHealth - amount);
|
|
OnHealthChanged?.Invoke(_currentHealth, stats.MaxHealth);
|
|
|
|
// ⭐ 피격 시 트리거 및 상태 리셋 함수 호출
|
|
OnHit();
|
|
|
|
OnHitEvent?.Invoke(); // 이벤트 발생
|
|
|
|
if (!IsDead) StartHit();
|
|
if (_currentHealth <= 0) Die();
|
|
}
|
|
|
|
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
// ⭐ [추가] 피격 시 공격 상태 리셋 (핵심!)
|
|
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
public void OnHit()
|
|
{
|
|
if (animator != null)
|
|
{
|
|
// 1. 남아있는 공격 트리거를 강제로 꺼버림 (유령 공격 방지)
|
|
animator.ResetTrigger("Attack");
|
|
|
|
// 2. 다른 공격(예: 투척) 트리거가 있다면 그것도 리셋
|
|
animator.ResetTrigger("Throw");
|
|
}
|
|
|
|
// 3. PlayerAttack 스크립트의 공격 중인 상태 플래그도 강제로 꺼줌
|
|
if (attackScript != null)
|
|
{
|
|
attackScript.IsAttacking = false;
|
|
}
|
|
|
|
Debug.Log("<color=yellow>[Combat]</color> 피격으로 인해 공격 예약 및 상태가 초기화되었습니다.");
|
|
}
|
|
|
|
private void StartHit()
|
|
{
|
|
isHit = true;
|
|
// 인스펙터에 적힌 피격 애니메이션 이름(HitAnime) 재생
|
|
if (animator != null) animator.Play("HitAnime", 0, 0f);
|
|
|
|
CancelInvoke(nameof(OnHitEnd));
|
|
Invoke(nameof(OnHitEnd), 0.25f);
|
|
}
|
|
|
|
public void OnHitEnd() { isHit = false; }
|
|
|
|
private void Die()
|
|
{
|
|
IsDead = true;
|
|
Cursor.visible = true;
|
|
Cursor.lockState = CursorLockMode.None;
|
|
OnDead?.Invoke();
|
|
}
|
|
|
|
public void Heal(float amount)
|
|
{
|
|
if (IsDead) return;
|
|
_currentHealth = Mathf.Min(_currentHealth + amount, stats.MaxHealth);
|
|
OnHealthChanged?.Invoke(_currentHealth, stats.MaxHealth);
|
|
}
|
|
} |