예전에는 유니티로 UI를 만들때 NGUI를 많이 사용했습니다. 다른 GUI 툴킷도 있었지만 대부분은 NGUI를 사용했고, 사실상 표준(De Facto)이라고 할 수 있는 상황이었죠. 그러다가 유니티에서 NGUI의 개발자를 영입하고1 4.6에서 새로운 UI 시스템2이 추가됩니다. 초반에는 아무래도 부족한 점이 많았고 소스 변경도 불가능했기 때문에 그대로 NGUI를 쓰는 회사가 많았습니다.

하지만 NGUI도 버전이 올라가면서 사용법이 꽤나 많이 바뀌고, 유니티 UI 관련 자료도 늘어나면서 NGUI 대신 유니티 UI를 사용하는 곳이 점차 늘어나고 있습니다. 주관적인 판단이긴 합니다만, UI와 관련된 유니티 강좌를 보면 최근에는 대부분 유니티 UI를 사용하고 있고, NGUI는 몇 년 지난 것들이 대부분입니다.

저도 최근에는 NGUI 대신 유니티 UI를 사용하고 있는데, 이제는 충분히 NGUI 대신 사용할 만하다고 생각됩니다. 다만 대부분은 어렵지 않게 변경이 가능한데, 몇 가지 지원하지 않거나 사용방법이 다른 경우가 있어서 어떻게 처리했는지 대해 적어볼까 합니다.

선택영역 처리 문제

NGUI에서는 컬라이더(Collider) 컴포넌트를 붙여서 선택영역을 지정합니다. 일반적으로 BoxCollider를 붙이지만, 필요에 따라서는 다른 타입의 컬라이더를 붙여 선택 영역을 지정할 수 있었습니다. 예를 들어 선택영역을 원형으로 지정하고 싶다면 SphereCollider를 사용하는 것으로 처리할 수 있었습니다.

유니티 UI에서 아쉬운 점 중 하나는 선택영역이 따로 분리가 되어있지 않고, 비주얼 컴포넌트가 영역 지정의 역할을 같이 한다는 것입니다. 일반적인 버튼을 만든다고 할때, 이미지의 크기를 변경하면 선택영역도 그에 맞춰 자동으로 변경됩니다. 보통은 외곽 이미지에 맞추면 큰 문제가 없지만, 때로는 눈에 보이는 것과 실제 영역을 다르게 처리해야할 필요가 있습니다.

일반적인 버튼 구조

선택영역과 비주얼의 분리

해결방법은 별도의 더미 컴포넌트를 작성하여 붙이는 것입니다. Button 컴포넌트와 같이 붙어있던 비주얼 컴포넌트는 자식 게임오브젝트를 만들어 그쪽에 붙이고, Raycast Target 체크박스를 꺼줍니다. Button 컴포넌트에 트랜지션 효과를 지정했다면 대상을 바꿔줍니다. 그리고 Button 컴포넌트의 대상이 될 비주얼 컴포넌트의 알파값을 0으로 해서 보이지 않게 합니다. 저는 Graphic 컴포넌트를 상속받은 별도의 클래스를 만들었습니다만, Image 클래스를 그대로 써도 됩니다.

변경된 버튼 구조

이렇게 하면 선택영역은 보이지 않는 더미 컴포넌트가, 비주얼은 자식 오브젝트가 담당하게 되어 따로 크기를 지정할 수 있게 됩니다.

사각형이 아닌 선택영역 처리

이렇게 영역분리는 되었지만, 한가지 문제가 더 남아있습니다. 선택영역을 사각형에서 벗어날 수가 없다는 것입니다. 앞서 말한 원형이라던가, 영역이 사선 형태가 되어야하거나 하는 경우에는 일반적인 방법으로는 처리할 수가 없습니다. 이럴때 사용할 수 있는 것이 Image.alphaHitTestMinimumThreshold 프로퍼티입니다. 이 프로퍼티는 Image 컴포넌트에 연결되어있는 스프라이트 텍스처의 알파값을 조사하여, 지정한 수치 이상일때에만 Raycast 이벤트를 발생시킵니다. 알파값을 조사한다는 것에서 알 수 있듯, 이 기능을 사용하기 위해서는 대상 텍스처가 읽기 가능 상태여야 합니다.

그럼 원형의 버튼 영역을 만들어보겠습니다. 먼저 대상 형태의 텍스처를 준비하고, 텍스처 임포트 설정에서 텍스처 타입은 Sprite, Advanced에서 Read/Write Enable를 켜주고, 알파값만 읽을 것이므로 포맷은 Alpha 8로 합니다. 그리고 스프라이트 아틀라스를 사용하고 있다면 대상 외로 합니다.

마스크 텍스처 임포트 세팅

Image.alphaHitTestMinimumThreshold는 인스펙터에 노출되지 않으므로 인스펙터에서 조작할 수 있도록 클래스를 작성해서 붙여줍니다.

Image 컴포넌트의 스프라이트로 위에서 준비한 텍스처를 넣고, 보이지 않도록 컬러의 알파를 0으로 해줍니다. Image.alphaHitTestMinimumThreshold는 어디까지나 텍스처 자체의 알파값만으로 판단할 뿐, Image 컴포넌트의 컬러값에는 영향을 받지 않습니다. 그리고 문턱값을 적당히 조절해주겠습니다.

버튼 인스펙터 설정

테스트한 결과 원 외부에서는 작동하지 않는 것을 알 수 있습니다.

원형 영역 테스트 결과

유니티 UI의 소스 확인

NGUI는 설치하면 소스 형태로 들어오기 때문에 내부를 바로 볼 수 있었습니다. 사실 유니티 UI 역시 웹에 소스를 공개하고 있고, 경우에 따라서는 수정해서 빌드하는 것도 가능합니다. 내부적으로 어떻게 움직이는가 궁금하다면 이쪽에서 확인해보시기 바랍니다.

Unity UI Extensions

제 경우 유니티 UI의 문서를 보면서 “음 필요한 건 대충 다 있는 것 같은데… 이 정도면 넘어가도 되겠다”고 생각을 했었는데, 실제로 작업하다보니 “NGUI에는 있는데 여기에는 이게 없네”라고 생각되는 것들이 있었습니다. Center On Child 같은 스크롤 중 스냅 기능같은 것들이 그랬는데요, 다행히도 그런 것들을 만들어서 무료로 공개중인 곳이 있었습니다.

Unity UI Extensions라는 이름 그대로 유니티 UI에서 쓸만한 여러가지 유틸리티를 모아놓은 곳입니다. 이 문서에서 따로 정리하지는 못합니다만, 굉장히 많은 기능을 제공하고 있으니 “혹시 이런 기능 없나?”싶은 것이 있다면 이쪽에서 한번 찾아보시기 바랍니다.

  1. 사실 그리 오래가지 않아서 불화로 다시 나옵니다. 4.6이 발표되기 전에 나왔는데, 그래도 개발방향에 많은 영향을 주었다는 것을 발표 시기의 영상을 보면 알 수 있습니다. 

  2. 발표 시에는 uGUI(Unity GUI)라는 이름으로 불리웠습니다. 공식명칭이 아니라 유니티 문서에서는 사용되지 않습니다만, 웹에서는 여전히 uGUI라고 부르는 사람이 많습니다.