[Unity] 체력 게이지

Jihoon·2022년 4월 25일
0

MMO_Unity

목록 보기
18/22

WorldSpace UI

기존에 사용하던 UI들은 다 2D UI인데 만약 캐릭터 위에 체력 게이지를 2D UI로 처리한다면 캐릭터가 멀리 있을 때 캐릭터의 크기는 작지만 UI의 크기는 그대로인 현상이 발생한다. 즉 UI를 3D 공간에 위치시킬 필요가 있다.


먼저 Slider UI를 통해 HPBar를 구현한다.
캔버스의 Render Mode를 WorldSpace로 설정하면 3D공간에 UI를 위치시킬 수 있다. 또한 카메라를 지정해줘야 한다.

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

public class UI_HPBar : UI_Base
{
    enum GameObjects
    {
        HPBar
    }

    public override void Init()
    {
        Bind<GameObject>(typeof(GameObject));
    }
}

새 클래스를 정의해서 HPBar를 바인드하는 코드를 작성한다.

public T MakeWorldSpaceUI<T>(Transform parent = null, string name = null) where T : UI_Base
{
    if (string.IsNullOrEmpty(name))
        name = typeof(T).Name;

    GameObject go = Managers.Resource.Instantiate($"UI/WorldSpace/{name}");

    if (parent != null)
        go.transform.SetParent(parent);

    Canvas canvas = go.GetOrAddComponent<Canvas>();
    canvas.renderMode = RenderMode.WorldSpace;
    canvas.worldCamera = Camera.main;

    return Util.GetOrAddComponent<T>(go);
}

UIManager에 HPBar 같은 WorldSpace에 위치할 UI를 추가하는 함수를 작성한다. 기존 MakeSubItemUI() 함수와 거의 동일하지만 캔버스의 설정에서 Render Mode의 변경과 카메라 설정을 하는 코드를 추가했다.

void Start()
{
    ...
    Managers.UI.MakeWorldSpaceUI<UI_HPBar>(transform);
}

이후에 일단 PlayerController에 Start() 함수에 MakeWorldSpaceUI() 함수를 호출해서 플레이어에게 HPBar가 뜨게 해봤다.

이후 게임을 실행해보니 HPBar가 플레이어를 따라다니긴 하는데, 위치가 이상하고 그리고 플레이어의 방향에 따라 위치가 계속 변하는 오류가 발생한다.

이를 해결하기 위해서는 HPBar의 position과 rotation을 지정해줘야 한다.

private void Update()
{
    Transform parent = transform.parent;
    transform.position = parent.position + Vector3.up * (parent.GetComponent<Collider>().bounds.size.y);
    transform.LookAt(Camera.main.transform);
}

UI_HPBar 클래스에 Update() 함수를 작성하였다.
position을 부모(HPBar가 붙는 객체)의 콜라이더의 y좌표점으로 하고, 카메라를 계속 쳐다보게 해서 rotation을 지정하였다.


이후 게임을 실행해보니 UI가 반대로 보이는 오류가 발생한다. 이는 당연한 것이 플레이어(유니티짱)가 카메라를 바라 볼 때도 플레이 하는 입장에선 유니티짱의 뒷모습이 아닌 정면을 보게 된다. 똑같은 이유로 UI도 반대로 보이는 것이다.

private void Update()
{
    Transform parent = transform.parent;
    transform.position = parent.position + Vector3.up * (parent.GetComponent<Collider>().bounds.size.y);
    transform.rotation = Camera.main.transform.rotation;
}

따라서 rotation 값을 카메라의 rotation 값과 동일하게 설정한다면 제대로 작동할 것이다.

이후 게임을 실행해보니 정상적으로 작동하는것을 확인했다.

체력 게이지

Stat _stat;

public override void Init()
{
    Bind<GameObject>(typeof(GameObjects));
    _stat = transform.parent.GetComponent<Stat>();
}

private void Update()
{
    ...
    float ratio = _stat.Hp / (float)_stat.MaxHp;
    SetHpRatio(ratio);
}

public void SetHpRatio(float ratio)
{
    GetObject((int)GameObjects.HPBar).GetComponent<Slider>().value = ratio;
}

공격을 받을때 마다 체력바가 주는것을 구현하기 위해 UI_HPBar 클래스에 함수를 추가했다.

우선 스탯을 저장하는 Stat 클래스를 Init() 에서 가져온다. 그리고 그 Stat의 정보를 사용해서 Update() 함수에서 Slider의 value 값을 조정한다.

void OnHitEvent()
{
    if (_lockTarget != null)
    {
        Stat targetStat = _lockTarget.GetComponent<Stat>();
        Stat myStat = gameObject.GetComponent<PlayerStat>();
        int damage = Mathf.Max(0, myStat.Attack - targetStat.Defense);
        Debug.Log("Damage");
        targetStat.Hp -= damage;
    }
	...
}

그리고 PlayerController의 OnHitEvent() 함수를 수정한다.

이제 적의 인스턴스에 Stat 스크립트와 UI_HPBar 프리팹을 컴포넌트로 추가하고 적은 따로 스크립트를 통한 관리를 하지 않으므로 수동으로 UI_HPBar의 렌더 모드와 카메라를 설정한다.


이후에 게임을 실행해보니 원하는 대로 작동하는 것을 확인했다.

profile
클라이언트 개발자 지망생

0개의 댓글