Projext/Assets/Scripts/UI/Enemy/EnemyHP Ui.cs

97 lines
4.6 KiB
C#

using UnityEngine; // 유니티 기능을 불러올거에요 -> UnityEngine을
using UnityEngine.UI; // UI 기능을 불러올거에요 -> UnityEngine.UI를
using TMPro; // TextMeshPro를 사용할거에요 -> TMPro를
/// <summary>
/// 몬스터 체력바 UI — MonsterClass.OnHealthChanged 이벤트 연동
/// 몬스터 프리팹의 MonsterHP_Canvas에 부착
/// </summary>
public class MonsterHPUibar : MonoBehaviour // 클래스를 선언할거에요 -> 몬스터 체력바 UI를
{
[Header("--- 타겟 ---")] // 인스펙터 제목을 달거에요 -> 타겟 설정을
[Tooltip("MonsterClass가 붙어있는 몬스터 오브젝트")]
[SerializeField] private GameObject targetObject; // 변수를 선언할거에요 -> 타겟 오브젝트를 (몬스터 루트)
[Header("--- UI 요소 ---")] // 인스펙터 제목을 달거에요 -> UI 요소를
[Tooltip("HP_Filled (Image, Fill 방식)")]
[SerializeField] private Image hpFilledImage; // 변수를 선언할거에요 -> 체력바 Fill 이미지를
[Tooltip("HP_Text (TMP) — '현재HP / 최대HP' 표시")]
[SerializeField] private TextMeshProUGUI hpText; // 변수를 선언할거에요 -> 체력 텍스트를
// 캐싱된 참조
private MonsterClass _monster; // 변수를 선언할거에요 -> 몬스터 클래스 참조를
private void Awake() // 함수를 실행할거에요 -> 초기화 Awake를
{
// 타겟이 비어있으면 부모에서 자동으로 찾기
if (targetObject == null) // 조건이 맞으면 실행할거에요 -> 타겟이 설정 안 됐다면
{
targetObject = transform.root.gameObject; // 할당할거에요 -> 최상위 부모 오브젝트를
}
if (targetObject != null) // 조건이 맞으면 실행할거에요 -> 타겟이 있다면
{
_monster = targetObject.GetComponent<MonsterClass>(); // 가져올거에요 -> MonsterClass를
if (_monster == null) // 조건이 맞으면 실행할거에요 -> 직접 못 찾았다면
{
_monster = targetObject.GetComponentInParent<MonsterClass>(); // 가져올거에요 -> 부모에서 MonsterClass를
}
}
}
private void OnEnable() // 함수를 실행할거에요 -> 활성화 시 OnEnable을
{
if (_monster != null) // 조건이 맞으면 실행할거에요 -> 몬스터가 있다면
{
_monster.OnHealthChanged += OnMonsterHealthChanged; // 등록할거에요 -> 체력 변경 이벤트 리스너를
}
// 활성화 시 즉시 UI 갱신 (풀에서 재사용될 때 대비)
ResetUI(); // 실행할거에요 -> UI 초기화를
}
private void OnDisable() // 함수를 실행할거에요 -> 비활성화 시 OnDisable을
{
if (_monster != null) // 조건이 맞으면 실행할거에요 -> 몬스터가 있다면
{
_monster.OnHealthChanged -= OnMonsterHealthChanged; // 해제할거에요 -> 체력 변경 이벤트 리스너를
}
}
/// <summary>
/// MonsterClass.OnHealthChanged(currentHP, maxHP) 이벤트 콜백
/// </summary>
private void OnMonsterHealthChanged(float currentHP, float maxHP) // 함수를 선언할거에요 -> 체력 변경 콜백을
{
// Fill Amount 갱신
if (hpFilledImage != null) // 조건이 맞으면 실행할거에요 -> Fill 이미지가 있다면
{
float ratio = (maxHP > 0) ? currentHP / maxHP : 0f; // 비율을 계산할거에요 -> 현재 / 최대로
hpFilledImage.fillAmount = Mathf.Clamp01(ratio); // 값을 설정할거에요 -> 0~1 사이로 Fill Amount를
}
// 텍스트 갱신
if (hpText != null) // 조건이 맞으면 실행할거에요 -> 텍스트가 있다면
{
hpText.text = $"{currentHP:F0} / {maxHP:F0}"; // 텍스트를 설정할거에요 -> "현재 / 최대" 형식으로
}
}
/// <summary>
/// UI를 풀 체력 상태로 초기화 (스폰/재활성화 시)
/// </summary>
private void ResetUI() // 함수를 선언할거에요 -> UI 초기화를
{
if (hpFilledImage != null) // 조건이 맞으면 실행할거에요 -> Fill 이미지가 있다면
{
hpFilledImage.fillAmount = 1f; // 값을 설정할거에요 -> Fill을 꽉 채우기로
}
// _monster가 있으면 실제 스탯으로 텍스트 갱신
if (hpText != null) // 조건이 맞으면 실행할거에요 -> 텍스트가 있다면
{
hpText.text = ""; // 텍스트를 비울거에요 -> 초기화로 (첫 OnHealthChanged에서 갱신됨)
}
}
}