플레이어 기준 좌측 상단에 배치된 플레이어 상태

 

목표: 플레이어 기본 체력(100)을 바탕으로 몬스터에게 공격을 받으면 체력이 닳아야한다. 

 

우선 체력바 구현을 위해 UI → Slider 생성

 

필요없는 Handle Slide Area는 제거

 

 

Slider의 Value 값(0~1)을 조절하여 HP가 깍히도록 할 예정

 

 

하트 아이콘을 좌측에 배치하고

 

현재 HP와 경계 및 가시성 향상을 위해 Background를 검은색으로(화살표 표시)

 

HP 영역은 Background 보다 작게 설정(좌, 우, 위, 아래)

 

체력을 표시할 HealthText는 UI 기준 우측하단에 배치하면 UI 설정은 끝난다.

 

public class PlayerStatData
{
    [field: SerializeField] public float MaxHealth { get; private set; } = 100f;
    [field: SerializeField] public float CurrentHealth { get; private set; } = 100f;
}

public class PlayerSO : ScriptableObject
{
    ... 중략
    [field: SerializeField] public PlayerStatData StatData { get; private set; }
}

 

최대 체력을 설정하여 ScriptableObject에서 관리한다.

 

PlayerCondtion.cs를 만들어 플레이어에 붙혀주고

 

public class PlayerCondition : MonoBehaviour
{
    public PlayerStatData playerStatData;
    public BugStats bugStats;
    public Slider healthBar;
    public TextMeshProUGUI healthText;
    
    private float currentHealth;
    private float maxHealth;

    private void Start()
    {
        currentHealth = playerStatData.CurrentHealth;
        maxHealth = playerStatData.MaxHealth; 
    }

    private void Update()
    {
        HpUpdate();
    }

    public void HpUpdate()
    {
        if (healthBar != null)
        {
            healthBar.value = currentHealth / maxHealth;
            healthText.text = $"{currentHealth}/{maxHealth}";
        }
    }

    public float GetCurrentHealth()
    {
        return currentHealth;
    }

    public void TakeDamage(float damage)
    {
        currentHealth -= damage;
        Debug.Log($"플레이어가 {bugStats.bugName}에게 {damage}의 공격을 받았습니다. 현재 체력: {currentHealth}");

        if (currentHealth < 0)
        {
            Destroy(gameObject);
            Debug.Log("사망");
        }
    }
}

 

currentHealth, maxHealth 변수를 선언해서

 

시작시 초기화를 진행 update에서 변화된 value값을 반영해준다.

 

GetCurrentHealth() 메서드는 몬스터가 공격시 현재 체력을 호출하기 위한 메서드

 

TakeDamage 메서드는 몬스터에게 공격받을 시 체력 감소 메서드

 

using Unity.VisualScripting;
using UnityEngine;

public class BugAttackingState : BugState
{
    private BugStats bugStats;
    private float attackCoolTime = 2.0f;
    private float lastAttackTime;
    public override void Enter()
    {
        bugStats = bug.bugStats;
        Debug.Log("버그 공격");
        lastAttackTime = 0;
    }

    public override void Update()
    {
        lastAttackTime += Time.deltaTime; // 경과시간누적
        if (lastAttackTime > attackCoolTime) // 쿨타임이 지났는지 확인
        {
            PlayerAttackDamage();
            lastAttackTime = 0; // 마지막 공격 시간 업데이트
            bug.ChangeState(bug.chasingState); 
            Debug.Log("플레이어 공격중");
        }
    }

    public override void Exit() { }
    ... 중략
}

 

몬스터 공격 상태 패턴 스크립트

 

가장 어려웠던 부분은 Update 부분인데

 

update에서 호출하다보니 몬스터가 공격을 하는 조건을 걸어야 했는데

(그렇지 않으면 매프레임마다 공격하므로 플레이어 바로 die..)

 

처음에는 Time.time(에디터 실행후 경과시간)을 기준으로 로직을 구성했으나

 

여전히 의도대로 되지않아 튜터님께 Help 요청..

 

결론은 debug 결과 실제로는 생각대로 작동하지 않았다.

(내가 생각한 것과 다를 수 있으니 Debug의 중요성을 말씀하심)

 

Time.deltaTime(이전 프레임이 끝나고 현재 프레임 시작되기까지 걸린 시간)으로 로직을 수정했다.


관련 코드 해석

 

lastAttackTime(마지막 공격 이후 시간)을 처음 진입시 0으로 초기화 해주고

 

  update에서 매프레임마다 Time.deltatime을 누적하고

 

attackCoolTime 보다 커지면 공격 실행 후 lastAttackTime 0으로 초기화 되면서

 

추적 로직으로 전환, 이후 2초 이상 경과시 다시 공격모드로 전환되는 원리


 

+ Recent posts