Posted in: Unity, 프로젝트 When the Spring comes

12. HP UI 만들기

플레이어 체력이 떨어진다면 HP 바가 깎이는 기능을 만들었다.

캔버스 게임 오브젝트를 만든 후 자식으로 HP바 이미지를 넣었다. HP바의 백 그라운드를 넣고 안 넣고는 개인 자유.

유니티의 이미지는 Image Type을 통해 스프라이트를 특정 순간에 줄일 수 있다.

  • Image Type <- Filled로 설정하면 이미지의 비율 변경 가능
  • Fill Method <- 이미지가 채워지는 방향을 설정 가능
  • Fill Amount <- 해당 이미지가 채워진 수치 (0 ~ 1)

플레이어의 체력이 닳으면 Fill Amount의 수치 조절을 통해 HP를 직관적으로 보여주는 것. 당연히 그 기능은 스크립트로 만든다.

public float myCurrentValue
{
    get
    {
        return currentValue;
    }

    set
    {
        if(value > myMaxValue) currentValue = myMaxValue;
        else if(value < 0) currentValue = 0;
        else currentValue = value;

        currentFill = currentValue / myMaxValue;
    }
}

private void Start() {
    healthPointBar = GetComponent<Image>();
    playerStat = GameObject.Find("Scopeia").GetComponent<PlayerStat>();

    //현재 체력 초기화
    Initialize(playerStat.health, playerStat.health);
    checkStat = playerStat.health; //체크용 스탯 넣음
}

public void Initialize(float currentValue, float maxValue)
{
    myMaxValue = maxValue;

    myCurrentValue = currentValue;
}

프로퍼티로 myCurrentValue에 값이 들어오면 currentFill의 값을 바꾼다. 최대 스탯과 현재 스탯이 같으면 1이고 현재 스탯이 줄어들때 마다 currentFill의 수치가 줄어든다.

private void Update() {
    CheckStat(playerStat.health);

    if(currentFill != healthPointBar.fillAmount)
    {
        //Mathf.Lerp(시작값, 끝값, 기준) -> 부드럽게 값을 변경 가능
        healthPointBar.fillAmount = Mathf.Lerp(healthPointBar.fillAmount, currentFill, Time.deltaTime * lerpSpeed);
    }
}

private void CheckStat(float stat)
{
    if(checkStat > stat)
    {
        myCurrentValue -= (checkStat - stat);
        checkStat = stat;
    }
}

Update()를 통해 매 순간마다 플레이어 스탯을 체크하고 플레이어 스탯이 달라진다면 myCurrentValue에 플레이어가 받은 대미지만큼 깎이게 해놓았다.

currentFill의 값과 현재 HP바의 Fill Amount가 다르다면 Fill Amount를 적절하게 깎아주면 된다.

좀 답답했던게 플레이어 스탯 스크립트에 UI를 제어할려고 했었는데 플레이어가 죽으면 플레이어 게임 오브젝트를 없어지게 해놨더니 플레이어 체력을 못받아와서 HP바 UI는 아직 1칸이 남아있는데 플레이어는 없어지는 해프닝이 벌어졌다.

나중에 플레이어 사망 애니메이션 만들고 게임 오브젝트를 없애는 게 아니라 다르게 바꿔야 겠지만, 결국에는 HP바 스스로 관리하게 바꾸었다.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class StatUI : MonoBehaviour
{
    private Image healthPointBar;

    public PlayerStat playerStat;

    public float lerpSpeed;

    private float currentFill;

    public float myMaxValue { get; set; }

    private bool check;

    public float checkStat;

    private float currentValue;

    public float myCurrentValue
    {
        get
        {
            return currentValue;
        }

        set
        {
            if(value > myMaxValue) currentValue = myMaxValue;
            else if(value < 0) currentValue = 0;
            else currentValue = value;

            currentFill = currentValue / myMaxValue;
        }
    }

    private void Start() {
        healthPointBar = GetComponent<Image>();

        playerStat = GameObject.Find("Scopeia").GetComponent<PlayerStat>();

        Initialize(playerStat.health, playerStat.health);
        checkStat = playerStat.health;
    }

    private void Update() {
        CheckStat(playerStat.health);

        if(currentFill != healthPointBar.fillAmount)
        {
            //Mathf.Lerp(시작값, 끝값, 기준) -> 부드럽게 값을 변경 가능
            healthPointBar.fillAmount = Mathf.Lerp(healthPointBar.fillAmount, currentFill, Time.deltaTime * lerpSpeed);
        }
    }

    public void Initialize(float currentValue, float maxValue)
    {
        myMaxValue = maxValue;

        myCurrentValue = currentValue;
    }

    private void CheckStat(float stat)
    {
        if(checkStat > stat)
        {
            myCurrentValue -= (checkStat - stat);
            checkStat = stat;
        }
    }
}

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 항목은 *(으)로 표시합니다