본문 바로가기
개발일지/게임개발

[Unity]Project_DT - Slider를 사용한 HP Bar 제작, 방어도 기획, 구현

by 라이티아 2025. 11. 3.

UI 구성을 조금 변경했다
1인 플레이에 좀 더 시점을 맞추고, 직관적으로 보이도록 디자인한다

이제 여기에 slider를 이용하여 플레이어, 적의 체력을 보여줄 체력바를 만들려 한다

 

using UnityEngine;
using UnityEngine.UI;

public class CharacterHPBar : MonoBehaviour
{
    [Header("체력바 Slider")]
    [SerializeField]
    private Slider _HpBar;

    [Header("캐릭터 스크립트")]
    [SerializeField]
    private Character _character;

    void Awake()
    {
        _HpBar = GetComponent<Slider>();

        _HpBar.maxValue = _character.MaxHP;
        _HpBar.value = _character.CurrentHP;
    }

    void Update()
    {
        _HpBar.value = _character.CurrentHP;
    }
}

HP는 character스크립트에서 가져와 사용한다

 

이제 이를 할당해 주면 자동으로 업데이트가 된다

잘 반영 되는것을 볼 수 있다

 

 

이제 방어도를 구현한다

더보기

방어도 해당 수치가 있을시 체력 대신 해당 수치로 피해를 받음

이때 데미지 연산식은 CurrnetHP = max(Damage - Shield, 0)가 됨

이때 shield값은 Shield - Damage를 연산해야함

만약 -값 체크가 true일시 전부 사용한 것으로 연산함

해당 수치는 얻은턴의 다음턴 시작 페이즈에 소실됨

다만 이렇게 될 경우 현재 character.cs에서 수치를 관리 하는데, 따로 분해 하는게 좋아 보인다

using UnityEngine;

public class Character : MonoBehaviour
{
    [SerializeField]
    private Stats _stats;

    void Awake()
    {
        _stats = new Stats();
    }
    public void TakeDamage(int damage)
    {
        if (_stats.Shield >= damage)
        {
            _stats.Shield -= damage;
        }
        else
        {
            damage -= _stats.Shield;
            _stats.CurrentHP -= damage;
        }

        if ( _stats.CurrentHP <= 0)
        {
             _stats.CurrentHP = 0;
            Die();
        }
    }

    private void Die()
    {
        Debug.Log($"{name} is dead");
        // 사망 처리 로직
    }
}

 

using UnityEngine;

[System.Serializable]
public class Stats
{
    [Header("최대 체력")]
    [SerializeField]
    protected int _maxHP = 10;
    
    [Header("현재 체력")]
    [SerializeField]
    protected int _hp = 10;

    [Header("방어도")]
    [SerializeField]
    protected int _shield = 0;

    public int Shield
    {
        get => _shield;
        set => _shield = value;
    }

    public int CurrentHP
    {
        get => _hp;
        set => _hp = value;
    }
    public int MaxHP
    {
        get => _maxHP;
    }
}

 

따로 분리해서 사용한다

 

 

이때 해당 클레스는 단순 데이터이기에 mono는 빼고 사용한다

 

이렇게 볼 시 인스펙터에서 쉽게 확인이 된다

 

방어도 5로 시작할시 방어도가 먼저 사용되는 것을 확인할 수 있다

 

이제 턴이 시작할 시 0으로 리셋 시켜야 한다

 

	[SerializeField]
    private TurnManager.TurnOwner _identity = TurnManager.TurnOwner.Player;

    public void ResetShield(TurnManager.TurnOwner turnOwner)
    {
        if (_identity == turnOwner)
            Stats.Shield = 0;
    }

 

turnmanager에서 자신의 턴이 돌아오면 초기화 하도록 유도하려 한다

    void Awake()
    {
        _stats = new Stats();
        TurnManager.Instance.OnTurnChanged += ResetShield;
    }

 

정상적으로 잘 처리되는 것을 확인할 수 있다

 

이제 카드에서 사용을 정의해야 하는데, 해당 기능은 현재 문제가 있어 따로 처리해야 할 것 같다