이제 UI_PopUp, UI_Scene, UI_World일때마다 어떻게 설정해주었는지를 작성해보겠습니다.
먼저 제일 간단한 UI_World 입니다.
UI_World는 사실 PopUp이나 Scene과 다르게
그저 몬스터 머리위에서 체력을 표시하거나, 상점 npc머리위에 상점입장이 표기되거나 하는 정도였기때문에
사용처가 많지않아 따로 클래스를 정의하진 않았습니다.
몬스터 체력바 UI스크립트입니다.
using System.Collections;
using System.Collections.Generic;
using Unity.VisualScripting;
using UnityEngine;
using UnityEngine.UI;
public class UI_MonsterHp : UI_Base
{
enum GameObjects
{
MonsterHPbar
}
public Monster monster;
private void Start()
{
Init();
}
public override void Init()
{
Bind<GameObject>(typeof(GameObjects));
monster =transform.parent.GetComponent<Monster>();
}
private void Update()
{
Transform parent = transform.parent;
if (parent == null)
{
Debug.LogError("parent가 null입니다!");
}
transform.position = parent.position + Vector3.up *(parent.GetComponent<Collider>().bounds.size.y);
transform.rotation = Camera.main.transform.rotation;
//MonsterHPbar를 변경해주는 로직
if (monster != null)
{
float hpRatio = monster.currentHp / monster.maxHp; // 체력 비율 계산
GetHp(hpRatio); // HP 바 갱신
}
}
void GetHp(float ratio)
{
GetGameObject((int)GameObjects.MonsterHPbar).GetComponent<Image>().fillAmount = ratio;
}
}
여기서 조금 고민했던점은 몬스터의 머리위를 지정해주기 위해서 collider의 위쪽방향으로 끝지점을 사용했다는 겁니다.
또한 항상 카메라를 바라보고있어야 어느각도에서도 체력바를 볼수있기때문에 처리를 해주었고 결과물을 보자면

이렇게 잘 적용된 모습입니다.
한 가지 주의해야할점은 UI를 World Space에서 띄우기위해서는 Canvas의 RenderMode를 World Space로 변경해줘야한다는겁니다.

그 다음으로 UI_Scene입니다. 이것도 사실 별거없습니다.
그 Scene에서 항상 존재해야하는 UI이기때문에 Scene시작과 동시에 띄워주기만한다면,크게 문제 될건없습니다.
개인적으로 개발하면서 가진 의문은" RPG장르에서 게임플레이중 무슨일이있어도 띄워져야하는 UI가 존재하는가?" 였습니다.
처음에는 플레이어의 상태표시 창 에대해 생각해보았습니다. 대부분의 경우 띄워져있는것은 맞지만 제가 즐겨하는 몬스터헌터,엘든링,원신 등의 게임에서 컷신 연출을할때에는 꺼놓긴 하더라고요. 그래서 이번 프로젝트를 진행하다가 정말 닫기 기능이 필요하지 않은 UI는 로딩 씬에서 표기하는 UI정도밖에 없었습니다.

결론적으로 분류를 해놓긴했지만 제 생각보단 그렇게 많이 Scene UI가 쓰이진 않았던거 같습니다. 하지만 다른 장르에 한해서는 필요 할 수있는 부분이기 때문에 이것또한 경험으로 쌓일거라고 생각하기로 했습니다.
마지막으로 PopUp_UI입니다.
이 부분에서 가장 중요한 부분은 무엇보다도 order관리 입니다. 제가 만약 인벤토리창, 스킬창 canvas 두개를 동시에 띄웠고 두 UI가 겹쳐져있는 상태에서 뒤에있는 인벤토리창을 클릭한다면 인벤토리창이 맨위에 표시되어야합니다.
저는 처음에 강의를보고 강의에서 구현한대로 Stack자료구조를 이용해서 구현후, 적용시켜보았습니다.
하지만 별로 좋은 방식은 아니었다고 생각됩니다. UI들을 순서대로 stack쌓는것은 좋았지만 거기까지였고, 제가 위에말한 클릭시 아래에있는게 위로 오게하려면 stack에서 해당 UI의 위에있는걸 전부빼고 다시 집어넣는 방식으로 구현했어야 합니다. 게다가 그렇게 구현한다고해도, 추가적인 문제는 존재했습니다.
그렇기 때문에 UI가 많아질수록 ordering관리가 급격하게 어려워졌고 버그가 미친듯이 발생했습니다.이 근본적인 구조적 문제때문에 제대로 구현하지 못한 부분이 많았습니다.

결과적으로
stack으로 제가 생각한대로 ordering을 구현하려했던 시도는 실패했습니다. 하지만 실패를 겪고나서 효율적인 방식을 탐색하다보니 LinkedList라는 자료구조가 이 문제를 해결하는데 안성맞춤인것을 깨달았습니다.
그리고 아이템에 마우스포인터를 올리면 정보를 표기해주는 기능을 구현하고 싶었는데 이 부분은 성공적으로 구현이되어 100%실패는 아니었고 얻어가는게 있었습니다.
IPointerEnterHandler, IPointerExitHandler를 이용하면 해당 UI에 마우스가 올라간것을 감지하고,정보창을 띄워주는 식으로 구현해보았습니다.

UI가 전체 프로젝트에서 시간에 쫓겨 강의에 나온대로 코드를 작성하다보니 이해를 못한채 기능을 사용해 능숙해지는데 많이 애를먹었습니다. 그래도 많이 사용해서 어떤게 문제점이있고 어떻게 개선해야하는지도 파악하는거 보니 익숙해진거 같습니다.
인벤토리창에 어떤 아이템이있는지는 플레이어의 인벤토리 데이터를 기반으로 표기되어야합니다. 그렇기때문에 다음 글에서는 Data를 어떻게 처리했는지에대해 글을 작성해보겠습니다.
'Unity' 카테고리의 다른 글
| #3. 데이터 관리 (0) | 2024.12.25 |
|---|---|
| #2 Managers 평가 + UI (0) | 2024.12.23 |
| #1. 기본 세팅 (Unity 프로젝트) (0) | 2024.11.15 |