Unity - (9) UI 구성

1. UI
1.1. 개요
- 간결하게 말하자면 중요하다.

<UI는 그냥 있어야만 한다>
- 첫번째로는 유저에게 상태를 알려줘야 하고 두번째는 상황마다 차이는 있을 수 있으나 게임 데이터를 유저가 조작한다.

<게임은 의외로 '알아야' 조작을 할 수 있다>
- 눈에 보이는 것 중 뽑으라고 한다면 가장 1순위다.
- 불편한 게임은, 그러니까 불편한 서비스는 유저에게 관심 받지 못한다.
- 유저가 가장 먼저 보고 서비스의 상태를 보려면 UI를 가장 먼저 보게 된다.
- 회사에 UI 작업부터 시작할 것인데 게임 핵심 로직과는 별개로 노동은 필요하다.

<UI가 엉망이면 자연스럽게 하기 싫은 게임이 된다>
- 미리 말하자면 눈에 보이는 것은 최적화와 직결되어 있는데 화면에서도 별에별 기법으로 최적화가 가능하다(CPU가 최대한 일을 덜하도록).
- 해당 사항은 링크를 참고할 것.
- 한 장의 프레임을 구성하기 위해 순차적으로 모니터링을 할 수 있음.
- 분석 툴에 익숙해질 필요가 존재.
- 프로젝트 할 때 최적화 관점을 생각할 때 완성이 1순위 그 다음이 최적화일 것이다.
1.2. 피봇, 앵커
- UI는 게임 오브젝트이며 살짝 다른 느낌이지만 Transform도 가진다.

- 그 다음, 2를 누르거나 2D를 누르고 더블 클릭을 한다.
- 게임에 틀어지는 화면에 따라 맞춘다.
- 이미지를 추가한다.

- UI를 진지하게 연출하려면 많은 기술들이 필요하겠지만 일단은 간결히 진행.
- 배치를 위해 필요한 것은 앵커와 피벗이라는 개념이 있다.
- 이게 UI를 질문할 때 가장 핵심 질문이다.
- 가장 먼저 피벗만 생각하면 기준점이다.

<기준을 중심으로 같이 딸려간다>
- 즉, 자기 자신이 가진 기준점이고 앵커는 부모에서 찍어준 피벗의 느낌이다.
- 부모의 크기가 변경될 때 따라가야 한다.
- 파란색 점을 주의해서 보도록 하자.

- 앵커부터 설명하도록 하면 해상도가 변경될 때 잘리기도 한다.
- 화면의 어딘가를 기준으로 맞추겠다라는 것이 필요하다.
- 디폴트로 맞춰지긴 했지만, 이 상태에서 Alt를 누르고 왼쪽 상단을 클릭하면 부모를 기준으로 그 왼쪽 상단에서만 고정이 된다.


- 이렇게 앵커 영역이라고 하여 고정된 핀처럼 화면 비율에 맞춰 대응이 된다.
- 그래서 게임 오브젝트인 UI에 대해 구조를 어떻게 잡느냐에 따라 상당히 쓰기 편해지는 경우가 있다.
- 예를 들어 캔버스 하위로 작은 오브젝트를 넣게되면 Rect Transform이 붙게 된다.

- 당연히도 UI에 대한 프리팹도 가능하다.
- 게다가 프리팹화가 가능하니 모듈화가 가능하다.
- 앵커를 통해 부모를 기준으로 위치를 잡는다고 생각하면 된다.
- alt를 통해 바로 이동이 가능했는데 Shift를 누르게 되면 앵커만 이동을 하는 것을 볼 수 있다.

1.3. Image와 Sprite
- 이제 이미지를 손댄 김에 추가를 해주고 이미지 형식을 바꿔줘야 한다.

- 그리고 넣어주면 된다.

- 이미지로 꼼수를 부려볼 수 있는 것이 있다.

- 그림판으로 빈 이미지를 하나 스프라이트로 만든 다음에 체력바 UI를 만들 수 있다.
- 또한 Toggle은 bool값 반환의 UI이다.
- slider, scrollbar 등은 조절부로 사용할 수 있고 원하는 Icon을 선택할 수 있을 듯.
1.4. Text
- 이제 압도적으로 사용하는 것은 Text라는 것을 먼저 보도록 하자.
- 정확히는 Text-MeshPro이다.

- 당연히 Text를 적을 수 있게끔 되어 있고 이 컴포넌트에 접근해서 넣을 수 있다.

- 단, 현재는 한글을 지원하지 않는 폰트이므로 받을 필요가 존재.
- 일단 링크를 볼 것.

-
프로젝트상에서는 가급적으로 ignore를 시켜놓고 쓰는 것이 좋다.

-
폰트에서 깨지거나의 문제는 Atlas 쪽을 보도록 하자.

1.5. Button
- 버튼도 많이 사용한다.

- 하지만 가급적으로 드래그 앤 드랍으로 이벤트를 추가하는 것은 하지 않도록 해야 한다.
- 기능이 단순하면 상관은 없겠지만 소스 코드로 처리하는 방식으로 하는 것이 좋을 것.
- 씬 하나 만들고 실습해보자.

- 배경과 버튼 설비 후 스크립트 생성.



- 이 순서로 진행



using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
public class TitleSceneController : MonoBehaviour
{
[SerializeField] private Button _startButton;
private void OnEnable() => BindButtonEvents();
private void OnDisable() => UnbindButtonEvenets();
private void BindButtonEvents()
{
_startButton.onClick.AddListener(LoadGameScene);
}
private void UnbindButtonEvenets()
{
_startButton.onClick.RemoveListener(LoadGameScene);
}
public void LoadGameSc
1.6. script를 통한 연동
- 인게임 씬에서 TextMeshPro를 띄워놨었는데 장탄수를 세팅해볼 것이다.
- 아까는 버튼의 참조를 썼고 이번에는 TextMeshPro로 가져가볼 것이다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using TMPro;
public class PlayerUIController : MonoBehaviour
{
[SerializeField] private TextMeshProUGUI _magazine;
}
- UI 갱신 기능 추가.
- Weapon에서 프로퍼티로 가져와도 되지만 따로 변수를 선언하여 다음과 같이 해볼 것.
public int CurrentMagazine => _currentMagazineCount;
public int MaxMagazine => _magazineCount;
- 가져올 것. 기본적인 사항은 포함하여.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using TMPro;
public class PlayerUIController : MonoBehaviour
{
[SerializeField] private TextMeshProUGUI _magazine;
private PlayerWeapon _weapon;
private void Awake() => CacheComponents();
private void Update() => RefreshMegazineUI();
public void RefreshMegazineUI()
{
_magazine.text = $"{_weapon.CurrentMagazine} / {_weapon.MaxMagazine}";
}
private void CacheComponents()
{
_weapon = GetComponentInChildren<PlayerWeapon>();
}
}
- 엔진으로 돌아가 설정하면 다음과 같음.

1.7. WorldSpace UI
- 이번엔 WorldSpace를 통한 체력 만들기를 해볼 것.



- 이런 식으로 설정 가능.




