저번에 DOTween을 공부하면서 UI에 대해서 좀 더 자세히 알아보고 싶은 마음이 들어서 UI Tool Kit에 대해서 알게되어서 이번 기회에 조금이나마 알아두면 좋을것 같아서 공부를 진행했다.
Unity Tool Kit은 유니티의 3세대 UI 라고 할 수 있다.

1세대 UI는 코드 기반의 IMGUI를 사용했었다. 당연하게도 코드 기반이다보니 사용성이나 성능 모든 면에서 게임의 UI로 사용하기에는 부족했다. 그래서 NGUI라는 플러그인을 사용하기도 했다.
새롭게 제시된 2세대 UI가 현재까지 내가 게임 개발할 때 사용해온 UGUI 방식이다. 이 방식은 유니티 Scene에서 UI를 만들어가는 오브젝트 기반의 방식이다.
그리고 그 다음으로 나온 것이 현재도 계속해서 업데이트 중이 UI Tool Kit이다. 유니티는 UI ToolKit이 웹 기반의 기술에서 영향을 받았다고 한다.
웹 기반 기술?
위와 같은 구조의 웹 기반 기술에 영향을 받았고 이를 각각 USS, UXML, C#으로 구현해서 실제로 아래와 같이 웹 기반의 기술을 UI ToolKit에 적용시켰다.

간단한 프로젝트를 한 번 만들어보자.

레이아웃과 구조를 담당한 uxml 파일을 하나 만든다. Create > UI ToolKit > UI Document

UTK에서는 대부분의 UI 작업을 게임 씬이 아니라 이 uxml 파일에서 작업하게 된다. 이 uxml이 게임 위에서 UI를 나타내도록 해보자.
빈 오브젝트를 하나 만들고 UI Document 컴포넌트를 추가해주고 uxml 파일을 연결해준다.

Panel Setting Error?
우리가 UGUI에서 UI를 화면에 그려주기 위해서 Canvas를 만들고 그 위에 작업을 했듯이 Panel Setting은 uxml로 만든 UI를 게임 씬에 그려주기 위한 일종의 틀이다.
Panel Setting도 만들어보자. Create > UI ToolKit > Panel Settings Asset

패널 전체에 적용할 테마나 텍스트 설정을 해줄 수 있는데, 대부분은 기본 설정을 사용해도 되는데, Scale Mode는 확인하고 넘어가자. Scale Mode는 Canvas에 붙어있던 Canvas Scaler라고 보면 된다. 해상도를 고정해서 다룰 것이기 때문에, Constant Pixel Size를 설정한다.

1080 * 1920 고정 해상도를 사용할 예정이다.
이제 이 Panel Settings를 연결해주면 기존 Panel Setting이 없다는 오류가 사라진다.

이제 uxml을 더블 클릭해서 UI Builder를 열어보자.

좌측의 Hierachy 셉션을 보면 uxml 파일이 있는데, 해당 부분이 UI의 계층 구조를 보여주는 곳이다. 에디터의 하이어라키와 다른 점은 게임 오브젝트가 아닌 UI를 구성하는 요소만 나열된다는 것이다.

그 밑의 Library 세션은 UI를 만들 때 사용할 요소들이 담겨져 있다.

가운데는 말그래도 뷰포트로 만든 UI를 확인하는 곳이다.

이 때 기본 테마를 확인할 수 있다. UI Builder는 UI의 확장 프로그램을 만들때 사용하던 도구이고 지금도 그렇게 사용되고 있다. 그래서 게임을 만들때는 Unity Default Runtime Theme이 선택되어 있는지 확인해야힌디. 그래야 인-게임에서 동일하게 출력된다.
뷰포트의 uxml을 선택하고 인스펙터의 Canvas Size에서 Match Game View를 선택하면 게임 뷰에서 지정한 사이즈로 커진다.

BackGround를 체크하면 Color, Image, Camera로 설정할 수 있다. 카메라에 Main Camera를 연결하면 메인 카메라가 렌더링하는 화면을 설정해놓고 UI 작업을 할 수 있다.
이제 하단과 같이 되어있다면 UI를 만들 준비 과정이 끝났다.

먼저 Library > Containers > VisualElement 끌어다 놓는다. VisualElement는 UI Tool Kit에서 가장 기본이 되는 구성요소로 UGUI의 게임 오브젝트와 이미지를 담당해주는 요소라고 생각하면 된다. (hrml의 <div> 태그를 담당하는 역할을 한다.)

우측의 인스펙터를 통해 Visual Element의 크기, 색상 같은 스타일을 설정해 줄 수 있다.

만약 게임 뷰에 바로 갱신이 안되면 한 번 Play 해주면 해결된다.
UGUI에서 UI 게임 오브젝트를 복사하면 동일한 위치에 중첩되서 복사되지만 툴킷에서는 Vertical layout Group을 적용한 것처럼 쌓이게 된다.

부모 VisualElement의 Flex가 그 역할을 해주고 있다.

Direction
또한 Align을 통해 정렬되는 기준도 바꿀 수 있다.
Flex와 Align을 잘 사용하면 아래와 같이 설정해줄 수도 있다.


그 다음 이미지를 넣을 Visual Element를 2개 넣어주고 이후에 넣을 애니메이션을 위해 이름을 바꿔준다.
이렇게 만든 이름, 즉 ID는 나중에 스크립트에서 UI의 특정 요소에 접근하거나 스타일시트에서 스타일을 적용할 대상을 특정 지을때 사용한다.
그런 다음 Backgounrd > Image에서 이미지를 불러온다. 이후에 아래와 같이 배치될 수 있도록 Align과 Flex를 설정해보자.

사진이 맘대로 확대되고 % 설정 느낌으로 채워진다면 Shrink와 Grow를 살펴보면 된다. 해당 관련된 개념은 원래 CSS의 개념이다. 설명하면 아래와 같다.

Grow : 부모 요소의 넓이보다 자식 요소들의 모든 넓이가 적을 때 사용할 수 있다. 즉, 자식들을 모두 넣었는데도 넓이가 남으면 입력한 숫자의 비율에 맞게 나눠 가진다. 모두 같은 숫자면 당연히 모두 같은 넓이로 채워진다.

즉, 자식이 자동으로 아이템 너비가 확대되거나 축소되지 않도록 하려면 반드시, Shrink와 Grow를 0으로 설정해야한다.
[이미지 출처 : CSS 플렉스박스(flex) flex-grow와 flex-shrink 속성의 완벽 이해 ]
적당히 배치하고 나면 아래와 같이 된다. 이 때 Space-Around를 사용했다.

Space-Between VS Space-Around
기본적으로 UI Tool Kit은 Flex를 이용해서 다양한 해상도에 대응하는 반응형 UI를 만들게 된다.
아래와 같은 하단 UI를 만들어보자.

다음과 같이 Label 2개와 Button을 넣어주고 Label 내용을 채워준다.

Label의 텍스트는 Attributes > Text에서 설정해줄 수 있다.
줄바꿈은 Text > Wrap에서 설정 가능하다.
놀랍게도 별도의 텍스쳐가 필요했던 기존과는 달리 UI Tool Kit은 모서리가 둥근, 라운드 버튼을 쉽게 만들 수 있다. Border의 Radius를 20으로 하면 반지름이 20px인 원으로 모서리를 처리하겠다는 뜻이다.


확대해보면 모서리에 테두리가 그려져있는데 Border의 Width에 1px이 기본값으로 들어가 있어서 그렇다. 0으로 고쳐주면 테두리가 없어진다.
하나 더 놀라운 점은 기존의 텍스쳐를 썼을때와 달리 확대 해도 계단 현상, 픽셀이 깨지는 현상이 전혀 없다. 이는 UI Tool Kit에서는가 텍스쳐 없이 선명한 UI를 제작할 수 있도록 하기 때문이다.
적절한 여백은 가독성과 시인성 모두에 큰 영향을 미치기 때문에 적절한 여백이 필요하다. 이 여백의 개념을 이해하기 위해선 Margin과 Padding에 대한 이해가 필요하다.

Border : 사이즈가 정의한 영역의 경계에 그려짐
Margin : 경계 바깥쪽에 생기는 여백 영역
Padding : 경계 안쪽에 생기는 여백 영역

각각의 레이블에 적절한 Margin, Padding을 줘서 위치를 조절한다.

버튼의 경우 부모 VisualElement를 100%, 240px로 Size를 설정해준다.

그 다음 Align과 Padding을 조절해주고 Label과 버튼이 들어있는 VisualElement들의 부모 VisualElement의 Padding도 적절히 값을 주면 아래와 같이 구성할 수 있다.


글꼴을 적용해보자. Window > text > Font Asset Creator로 간다. 글꼴을 Source Font에 끌어다 놓고 Generate Font Atlas를 눌러 Font Asset을 만들어준다.


그런 다음 Regular Font Asset의 Font Weight에 Bold Font Asset을 연결해준다.

이렇게 해야 UI Builder에서 Bold 옵션을 선택했을때 잘 적용된다. 그 다음 Regular와 Bold Asset 모두 Generation Settings에서 Atlas Population Mode를 Dynamic으로 바꿔주고 Apply 해준다.

Panel Settings에서 전체 Font를 관리할 수 있는데, Font 설정 파일을 추가로 만들어야해서 간단히 UI Builder에서 적용하도록 해보자. 단순히 Label을 고른다음의 Inspector의 Text의 Font Asset에서 설정해주면 된다.

이 방식 외에도 가장 상위의 Visual Element를 고르고 Font Asset을 적용해도 하위에 있는 모든 자식 Element의 Font가 동일하게 바뀐다.
웹에서 사용하는 Castcading 방식을 사용하기 때문이다. 기존의 UGUI 에디터 스크립터로 가능은 했지만 이런 스타일 체계를 지원하는 것은 굉장히 편리하다고 할 수 있다.
실행해보면 알겠지만 UI는 정상 출력이 되도 어떤 기능적인 부분은 하나도 없다. 버튼에 이벤트에 반응하도록 하면서 Unity UI의 스타일과 스타일 시트에 대해서 알아보자.
시작하기에 앞서 스타일과 스타일 시트에서 중요한 개념에 대해 알아두자.
우리가 지금까지 인스펙터에서 값을 수정한 부분의 앞에 흰색 줄로 표시되는 것을 확인할 수 있다. 이는 그 속성의 기본 값을 다른 값으로 덮어씌웠다는 것을 의미한다.

변화된 값과 속성들에 대한 정보는 uxml 파일 안에 UI 구조 레이아웃 정보와 함께 저장된다. 아래는 실제 uxml 파일의 내부 내용이다.

그 중에서도 <ui:Button>이 우리가 만든 버튼에 대한 정보이다.

이렇게 uxml 안에 항목 안에서 그때 그때마다 필요한 스타일을 지정해주는 것을 인라인 스타일이라고 한다. 쉽게 말하면 기본 값으로 속성 값이 지정되고 수정한 내용만 uxml 안에 추가로 저장되면서 스타일을 지정해준다고 생각하면 쉽다.
다시 기본값으로 되돌려 인라인 스타일을 적용시키지 않으려면 우클릭하고 Unset 해주면 된다.
이러한 인라인 스타일은 바로바로 직접 스타일 적용이 가능하고, UXML 안에 별도로 저장되는 장점이 있지만 규모가 커지면 관리가 어렵다는 단점이 있다.
이렇게 규모가 커져서 생기는 단점을 극복하고 체계적인 스타일 관리로 UI의 일관성을 유지하기 위해 나온 개념이 바로 스타일 시트이다.
그럼 스타일 시트는 어떻게 만들고 사용할까? 먼저 UI Builder의 좌측 상단의 + 버튼으로 Style Sheet (USS)를 만들 수 있다.

VScode로 열면 아무 내용도 없다. (아무런 스타일도 적용하지 않았기 때문이다.) 현재 버튼에 적용된 인라인 스타일을 USS 파일로 옮겨보자.
버튼을 선택한 후 인스펙터의 StyleSheet에 적절한 이름을 적어준다.

그 다음에 Extract Inlined Styles to New Class 버튼을 누른다. 그러면 StyleSheet > Style Class List 하단에 우리가 붙였던 이름의 스타일 클래스가 등록된 것을 확인할 수 있다.

또한 속성 앞의 수정했다고 표시해주던 하얀 표시들이 모두 사라졌다.

그리고 uss 파일 안에 스타일 클래스가 추가되었다. 이후에 uxml과 uss 파일을 VScode로 열어보면 uxml의 <ui:Button>에 스타일 클래스의 이름만 적혀있고 uss에는 button-blue 스타일 클래스에 대한 정보가 들어있다.
즉, 스타일 시트에서 해당하는 스타일 클래스에 대한 정보만 가져와 이 ui 요소에 적용하겠다는 것을 의미한다.


그럼 왜 스타일을 스타일 클래스의 형태로 스타일 시트 안에 관리하는 것이 유용할까?


좌측의 uss에서 스타일 클래스를 하이어라키 창의 UI 요소에 드래그해서 넣어주거나 Style Class에 직접 이름을 입력해서 Add Style Class to List 버튼을 눌러서 추가할 수도 있다.
기존의 UGUI에서 프리팹을 사용해서 얻을 수 있었던 이점처럼 이러한 재사용성과 유지보수의 용이함 때문에 스타일 시트가 굉장히 중요하다.
유니티가 제공하는 Pseudo 클래스로 버튼이 이벤트에 반응하도록 해보자. 스타일 클래스와 Pseudo 클래스의 차이는 아래와 같다.
유니티에서 지원하는 Pseudo 클래스 목록

이 중 hover(마우스가 위에)와 active(마우스로 클릭)를 사용해보자. Pseudo 클래스를 사용하려면 좌측 상단에서 기존 스타일 클래스 뒤에 ":(이벤트명)"를 추가해서 작성해주면 셀렉터가 추가된다.

이제 새롭게 추가된 셀렉터를 선택하고 인스펙터에서 어떠한 변화를 줄지 만들어줄 수 있다. 아래와 같은 변화를 주었다.


아래와 같이 잘 작동한다.

굳이 실행하지 않아도 우측 상단의 Preview로 UI의 동작을 확인할 수 있다. (프레임 드랍이 심하면 게임 씬으로 봐야한다.)
하지만 변화는 되지만 기존의 DOTween처럼 변하는 과정의 animation은 아직 없다. 간단한 변환 animation을 추가해보자.
좌측 상단의 클래스 시트에서 기본 셀렉터를 선택하고 인스펙터 맨 밑의 Transition Animation에서 변환 애니메이션을 줄 수 있다.

내부 속성들은 DOTween과 상당히 유사하다.

위 사진과 같이 설정하면 아래와 같이 애니메이션이 적용된다. ( 잘 보이라고 값을 좀 크게해놔서 추후에 작게 수정했다. )

uss 파일을 보면 끝부분에 Transition Animation과 Pseudo 클래스에 대한 내용이 추가되어 있다.
팝업 위에 뜨는 화면과 스크립트로 UI 요소를 애니메이션하고 전환 효과를 추가해보자.