UI HUD
UI HUD의 역할
- HP 상황을 띄워준다.
- 왼쪽 하단에 아이템의 개수 현황(코인, 키, )과 몬스터 수를 요약해서 보여준다.
- HUD 요소들은 다른 UI가 활성화될 때 보이지 않아야 함
필요한 변수들 선언
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class UI_0_HUD : MonoBehaviour
{
private static UI_0_HUD instance = null;
// UI Window
public GameObject UI_W_HUD = null;
// Detail
// HP
[SerializeField]
private List<GameObject> hpPrefabsList;
private List<GameObject> hpList = new();
[SerializeField]
private Canvas canvas;
[SerializeField]
private int interval;
private int hpNum = 0;
// Left side text
public Text KeyCount;
public Text CoinCount;
public Text BombCount;
public Text MonsterCount;
public GameObject HUDGroup;
public GameObject MiniMap;
// Manager
private StatusManager statusManager = null;
public static UI_0_HUD Instance
{
get
{
if (instance == null)
{
instance = FindObjectOfType<UI_0_HUD>();
if (instance == null)
{
GameObject singletonObject = new GameObject(typeof(UI_0_HUD).Name);
instance = singletonObject.AddComponent<UI_0_HUD>();
DontDestroyOnLoad(singletonObject);
}
}
return instance;
}
}
...
}
*Detail 부분에 HP는 다른 팀원이 구현했으므로 따로 설명하지는 않을 것이다.
- UI_0_HUD
- 싱글톤 패턴을 구현하기 위한 인스턴스
- Left side text
- HUD에 표시되는 특정 오브젝트의 수
기본 함수(Awake, Start, Update)
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class UI_0_HUD : MonoBehaviour
{
...
private void Awake()
{
if (instance == null)
{
instance = this;
DontDestroyOnLoad(this.gameObject);
}
else if (instance != this)
{
Destroy(gameObject);
}
}
// Start is called before the first frame update
void Start()
{
statusManager = StatusManager.Instance;
HpBarSet();
}
// Update is called once per frame
void Update()
{
}
...
}
Awake()
싱글톤 인스턴스 설정과 씬 전환 시 객체를 유지하게 만들고, 현재 오브젝트가 기존 인스턴스와 다른 경우 파괴하도록 만들어줬다.
Start()
HP를 표시하는 UI에서 StatusManager에서 HP를 가지고 와서 사용해야 하기 때문에 싱글톤 인스턴스에 접근하도록 만들고, HP UI를 세팅해 주는 함수를 호출했다.
UI Active 관련 함수
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class UI_0_HUD : MonoBehaviour
{
...
public void OpenUI()
{
if (UI_W_HUD != null)
{
UI_W_HUD.SetActive(true);
HUDGroup.SetActive(true);
MiniMap.SetActive(true);
foreach (GameObject HPList in hpList)
{
HPList.SetActive(true);
}
}
}
public void CloseUI()
{
if (UI_W_HUD != null)
{
UI_W_HUD.SetActive(false);
HUDGroup.SetActive(false);
MiniMap.SetActive(false);
foreach (GameObject HPList in hpList)
{
HPList.SetActive(false);
}
}
}
...
}
UI 매니저에서 각각의 UI 요소들의 Active 상태를 제어하는 OpenUI, CloseUI 함수를 정의해 유지보수성을 높였다.
상태 변화를 제어하는 것을 이 함수들을 사용하는 것으로 한정해 불필요한 활성화/비활성화로 부작용을 방지하도록 만들었다.
Left Side Text Update 함수
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class UI_0_HUD : MonoBehaviour
{
...
public void UpdateHUD()
{
KeyCount.text = ItemManager.Instance.GetKeyCount().ToString();
CoinCount.text = ItemManager.Instance.GetCoinCount().ToString();
BombCount.text = ItemManager.Instance.GetBombCount().ToString(); ;
}
public void MonsterCountHUDSet(int monsterNum)
{
MonsterCount.text = monsterNum.ToString();
}
...
}
이 부분은 HUD를 업데이트해 주는 부분이다.
HP UI 관련 함수들
이 부분은 다른 팀원이 작성한 부분으로 따로 설명하지 않겠다.
관련 로직이 궁금한 사람들은 아래 코드를 참고하길 바란다.
더보기
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class UI_0_HUD : MonoBehaviour
{
...
// HP Update Func
public void HpBarSet()
{
//hp 체력바 리셋
if (hpList.Count > 0)
{
for (int i = hpList.Count - 1; i >= 0; i--)
{
GameObject removeHp = hpList[i];
hpList.RemoveAt(i);
Destroy(removeHp);
}
hpNum = 0;
}
if (hpPrefabsList.Count < 4)
{
Debug.LogError("hpPrefabsList에 필요한 프리팹이 부족합니다.");
return;
}
//플레이어의 체력 상황에따라 체력바 재생성
if (statusManager.MaxHp > 0)
{
//최대체력 3당 체력베터리 1개 생성후 리스트에 추가
for (int i = 0; i < statusManager.MaxHp / 3; i++)
{
GameObject newHp = Instantiate(hpPrefabsList[0], canvas.transform);
newHp.transform.SetParent(canvas.transform, false);
RectTransform rectTransform = newHp.GetComponent<RectTransform>();
rectTransform.anchoredPosition = new Vector2(i * interval, 0); // 위치 조정 (임의로 설정)
hpList.Add(newHp);
hpNum += 1;
}
//임시체력 3당 임시체력베터리 1개 생성후 리스트에 추가
if (statusManager.TemHp > 0)
{
for (int i = 0; i < statusManager.TemHp / 3; i++)
{
GameObject newTemHp = Instantiate(hpPrefabsList[1], canvas.transform);
newTemHp.transform.SetParent(canvas.transform, false);
RectTransform rectTransform = newTemHp.GetComponent<RectTransform>();
rectTransform.anchoredPosition = new Vector2(hpNum * interval, 0); // 위치 조정 (임의로 설정)
hpList.Add(newTemHp);
hpNum += 1;
}
}
//전기1 전기베터리 1개 생성후 리스트에 추가
if (statusManager.Elect > 0)
{
for (int i = 0; i < statusManager.Elect; i++)
{
GameObject spark = Instantiate(hpPrefabsList[2], canvas.transform);
spark.transform.SetParent(canvas.transform, false);
RectTransform rectTransform = spark.GetComponent<RectTransform>();
rectTransform.anchoredPosition = new Vector2(hpNum * interval, 0); // 위치 조정 (임의로 설정)
hpList.Add(spark);
hpNum += 1;
}
}
//쉴드체력1당 체력베터리 1개 생성후 리스트에 추가
if (statusManager.ShieldHp > 0)
{
for (int i = 0; i < statusManager.ShieldHp; i++)
{
GameObject newShildHp = Instantiate(hpPrefabsList[3], canvas.transform);
newShildHp.transform.SetParent(canvas.transform, false);
RectTransform rectTransform = newShildHp.GetComponent<RectTransform>();
rectTransform.anchoredPosition = new Vector2(hpNum * interval, 0); // 위치 조정 (임의로 설정)
hpList.Add(newShildHp);
hpNum += 1;
}
}
}
}
public void HpBarPlus()
{
}
public void ShiledSet()
{
//쉴드체력이 소모될때 쉴드체력을 삭제
for (int i = hpNum - 1; i >= 0; i--)
{
if (hpList[i].name == "Shield_Heart(Clone)")
{
GameObject removeHp = hpList[i];
hpList.RemoveAt(i);
Destroy(removeHp);
hpNum--;
ShiledOn();
return;
}
}
}
private void ShiledOn()
{
//Hp체력바의 쉴드를 활성화
for (int i = 0; i < hpNum; i++)
{
if (hpList[i].name == "R_Heart(Clone)")
{
// 첫 번째 자식을 가져와 활성화
if (hpList[i].transform.childCount > 0)
{
hpList[i].transform.GetChild(0).gameObject.SetActive(true);
}
}
}
}
public void ShiledOff()
{
//hp체력바의 쉴드를 비활성화
for (int i = hpNum - 1; i >= statusManager.Shield; i--)
{
if (hpList[i].name == "R_Heart(Clone)" && hpList[i].transform.GetChild(0).gameObject.activeSelf)
{
hpList[i].transform.GetChild(0).gameObject.SetActive(false);
return;
}
}
}
public void HpSet()
{
if (statusManager.CurrentHp <= 3)
{
switch (statusManager.CurrentHp)
{
case 1:
hpList[0].transform.GetChild(1).gameObject.SetActive(true);
hpList[0].transform.GetChild(2).gameObject.SetActive(false);
hpList[0].transform.GetChild(3).gameObject.SetActive(false);
return;
case 2:
hpList[0].transform.GetChild(1).gameObject.SetActive(true);
hpList[0].transform.GetChild(2).gameObject.SetActive(true);
hpList[0].transform.GetChild(3).gameObject.SetActive(false);
return;
case 3:
hpList[0].transform.GetChild(1).gameObject.SetActive(true);
hpList[1].transform.GetChild(1).gameObject.SetActive(false);
hpList[0].transform.GetChild(2).gameObject.SetActive(true);
hpList[0].transform.GetChild(3).gameObject.SetActive(true);
return;
}
}
switch (statusManager.CurrentHp % 3)
{
case 0:
for (int i = 0; i < statusManager.MaxHp / 3; i++)
{
hpList[i].transform.GetChild(1).gameObject.SetActive(false);
hpList[i].transform.GetChild(2).gameObject.SetActive(false);
hpList[i].transform.GetChild(3).gameObject.SetActive(false);
}
for (int i = 0; i < statusManager.CurrentHp / 3; i++)
{
hpList[i].transform.GetChild(1).gameObject.SetActive(true);
hpList[i].transform.GetChild(2).gameObject.SetActive(true);
hpList[i].transform.GetChild(3).gameObject.SetActive(true);
}
break;
case 1:
hpList[((int)statusManager.CurrentHp / 3)].transform.GetChild(1).gameObject.SetActive(true);
hpList[((int)statusManager.CurrentHp / 3)].transform.GetChild(2).gameObject.SetActive(false);
hpList[((int)statusManager.CurrentHp / 3)].transform.GetChild(3).gameObject.SetActive(false);
break;
case 2:
hpList[((int)statusManager.CurrentHp / 3)].transform.GetChild(1).gameObject.SetActive(true);
hpList[((int)statusManager.CurrentHp / 3)].transform.GetChild(2).gameObject.SetActive(true);
hpList[((int)statusManager.CurrentHp / 3)].transform.GetChild(3).gameObject.SetActive(false);
break;
}
}
public void TemHpSet()
{
//임시체력 관리
for (int i = hpNum - 1; i >= 0; i--)
{
if (hpList[i].name == "RDis_Heart(Clone)")
{
switch (statusManager.TemHp % 3)
{
case 0:
hpList[i].transform.GetChild(0).gameObject.SetActive(true);
hpList[i].transform.GetChild(1).gameObject.SetActive(true);
hpList[i].transform.GetChild(2).gameObject.SetActive(true);
break;
case 1:
hpList[i].transform.GetChild(0).gameObject.SetActive(true);
hpList[i].transform.GetChild(1).gameObject.SetActive(false);
hpList[i].transform.GetChild(2).gameObject.SetActive(false);
break;
case 2:
hpList[i].transform.GetChild(0).gameObject.SetActive(true);
hpList[i].transform.GetChild(1).gameObject.SetActive(true);
hpList[i].transform.GetChild(2).gameObject.SetActive(false);
break;
}
return;
}
}
}
public void TemHpDel()
{
for (int i = hpNum - 1; i >= 0; i--)
{
if (hpList[i].name == "RDis_Heart(Clone)")
{
GameObject removeHp = hpList[i];
hpList.RemoveAt(i);
Destroy(removeHp);
hpNum--;
return;
}
}
}
public void HpDel()
{
for (int i = hpNum - 1; i >= 0; i--)
{
if (hpList[i].name == "R_Heart(Clone)")
{
GameObject removeHp = hpList[i];
hpList.RemoveAt(i);
Destroy(removeHp);
hpNum--;
return;
}
}
}
public void ElectDel()
{
for (int i = hpNum - 1; i >= 0; i--)
{
if (hpList[i].name == "Elect_Heart(Clone)")
{
GameObject removeHp = hpList[i];
hpList.RemoveAt(i);
Destroy(removeHp);
hpNum--;
return;
}
}
}
}
참고 사항
UI Manager
[Unity] UI Manager 구현
UI ManagerUI Manager 기본정보큰 UI의 틀이 있고 버튼을 통해 총 7개의 화면 전환이 있어야 한다.기본 정보를 보여주는 UI게임 기능인 프로그램의 정보를 띄워주는 UI인벤토리처럼 획득한 아이템 리스
gdoo.tistory.com
마무리하며..
HP 현황을 표시해 주고, 업데이트해 주는 부분이 개인적인 생각으로 비 효율적으로 설계된 것 같다.
큰 작업이 끝나면 이후 재설계 or 최적화를 해야 할 것 같다.
'Unity > Hackers Window' 카테고리의 다른 글
[Unity] UI 3 : DownLoad (0) | 2024.11.21 |
---|---|
[Unity] UI 2 : MyPC(Status UI) (0) | 2024.11.20 |
[Unity] UI Manager 구현 (0) | 2024.11.18 |
[Unity] Monster 구현 : M_VE - 2 (1) | 2024.11.17 |
[Unity] Monster 구현 : M_VE - 1 (1) | 2024.11.16 |