문제 상황
저격 총에서 특정 트리거가 입력되면 scope UI를 노출하는 기능을 구현하고 싶었다. 다만, 일반적인 PC 환경과는 달리 VR 환경에서는 양안 렌즈를 통해 유저가 입체적으로 오브젝트를 인지하도록 만들기에 2D UI를 구성하는데 어려움이 있었다.
문제 해결 과정과 테스트
사실 처음에는 그냥 무조건 2D로 UI를 구현하려고 했다. 내 머릿속의 3D UI는 world 내의 다른 오브젝트에 의해 언제든 가려질 수 있는 것이었고, 그렇기에 아래와 같은 목표를 달성하기 위해서는 무조건 Unity 내 canvas의 screen space로 UI를 구성한 것처럼 world에서 분리된 2D UI를 사용해야 된다고 생각했다.
- 화면의 최상단에 렌더링 돼야 한다.
- 다른 오브젝트와 충돌해서는 안 된다.
그래서, 대충 그림판으로 임시 scope 이미지를 만든 후에 widget blueprint를 생성해서 UMG(Unreal engine Motion Graphics)로 UI를 구성했다.
그 뒤에는 pawn의 camera에 widget component를 attach 한 다음에 UI를 screen space에 노출되게 설정해 봤다.
결과는 UI가 제대로 노출되지 않았다. Position이나 scale을 조정해 봐도 양안 렌즈 둘 모두에 정상적으로 노출되지 않았다. 캡처는 못했는데 대충 UI의 일부만 보이고 초점도 안 맞게 나왔다고 보면 된다.
그래서, 다음으로는 world space로 설정해서 테스트해 봤다. 결과는 아래와 같다.
영상에서는 한쪽으로 치우쳐져 있는데 실제로는 잘 나온다. 문제는 초점이 잘 안 맞고, 다른 오브젝트에 가려지거나 충돌한다는 것이었다.
이때 이후로 다시 screen space로 조금씩 다르게 테스트해보거나, HUD를 상속받아서 HUD 블루프린트에 UI를 넣어보는 등 이것저것 시도해 봤는데 전부 실패했다.
단순히 내 뇌피셜로만 테스트만 한 게 아니라 레딧이나 포럼들 찾아보면서 한 것들인데 하나 같이 다 실패하니까 머리도 안 돌아가는 것 같고 너무 피로했다..
그래서, 그냥 언리얼 커뮤니티에 글을 올리고 그날은 작업을 접었다.
[해결] VR 환경에서 UI는 어떻게 구성하나요?
대한민국 모임의 시작, 네이버 카페
cafe.naver.com
다음 날 확인해 보니 3D widget에 disable depth test를 활성화하라는 답변이 와있었다. 한 번 해봤다. 잘 됐다. 그것도 꽤. 허무했다.
자세한 해결 과정은 다음과 같다.
- 본인이 원하는 형태의 Widget Blueprint[A]를 구성한다.
- World 내 3D 공간에서 표시하기 위해 Actor Blueprint[B]를 만든다.
(추가로, 충돌 처리가 안 되도록 만들기 위해 No Collision으로 설정했다.) - [B]에 Widget Component를 추가한 후, [A]를 할당한다.
- Pawn의 Camera Component에 [B]를 부착한다.
([B]의 material이 one-side로 되어있을 경우, 카메라 측면에서는 안 보일 수 있으니 확인 후 필요에 따라 Z 축으로 180도 회전시킨다.) - [B]의 material에서 Blend Mode를 Translucent로 설정하고, Disable Depth Test를 True로 설정한다.
(Master material에서 설정해야 된다.) - 필요에 따라 [B]를 제어하여 UI를 활성화/비활성화한다.
결국 해결이 되니까 기분이 좋기는 했는데 아직 개념에 대한 이해가 정말 많이 부족하다는 생각이 들었다. 이슈를 해결하는 것도 좋지만, 왜 이렇게 된 건지, 어떻게 해결이 된 건지 알고 싶었다.
아래는 내가 이슈를 해결하는 과정에서 헷갈렸던 부분과 그 원리다. 하나씩 간단하게 살펴보고 마무리 짓도록 하자.
먼저 UMG와 UI, HUD의 관계에 대해서 살펴보자. 처음에는 이것들에 차이가 있는지 몰랐다. UMG라는 건 언리얼에서 개발할 때의 UI를 지칭하는 용어고, HUD는 플레이 화면에서의 UI를 지칭하는 용어인 줄 알았다. 실상은 완전히 달랐다.
- Unreal engine Motion Graphics (UMG)
언리얼 엔진에서 제공하는 게임 내 인터페이스 관련 그래픽 요소 디자인을 위한 도구다. widget이라는 이름으로 묶여 있는 UI의 구성 요소들(버튼, 체크박스, 슬라이더 등)을 조립해서 UI를 만들 수 있다.
이러한 작업은 widget blueprint에서 진행되며, designer 탭에서 UI의 시각적인 레이아웃을, graph 탭에서 UI의 기능을 스크립팅하여 구성할 수 있다.
Widget blueprint는 UMG의 핵심 구성 요소일 뿐 widget blueprint가 UMG의 전부라고는 할 수 없다. (DPI scaling, property binding 등 몇 가지 더 있다고 한다.) - User Interface (UI)
유저와 게임 간의 상호 작용이 가능하게 하는 그래픽 요소를 총칭하는 용어다. 일반적으로 게임 내의 정보를 단순 표기함으로써 유저 행동에 따라 게임의 상태가 어떻게 바뀌는지 유저에게 알리거나, 때때로 유저의 입력을 받아 게임 내 설정을 변경하기도 한다. - Head-Up Display (HUD)
게임 플레이를 하는 과정에서 유저에게 정보를 제공하는 UI의 일부다. 체력, 점수, 탄약 수, 미니맵 등과 같은 정보를 플레이 도중 표기함으로써 유저가 게임의 상태와 같은 정보를 인지하고 플레이에 활용할 수 있도록 돕는다.
사실 UI와 HUD를 별개의 것으로 보는 사람들도 있다고 하는데 나는 HUD가 아래 조건을 만족하는 UI라고 생각해서 위와 같이 정리했다.
- 게임 플레이 도중에 노출된다.
- 유저와 직접적으로 상호 작용할 수 없다.
- 유저에게 게임의 상태를 전달할 목적으로 사용된다.
다음으로는 disable depth test를 true로 설정했을 때, 왜 다른 오브젝트에 의해 가려지지 않는지에 대해 살펴보자.
먼저 depth test가 무엇인지 알아야 될 것 같다. Depth test는 쉽게 말해서 렌더링 비용을 줄이기 위한 과정 중 하나라고 보면 된다.
Depth test가 어떻게 렌더링 비용을 줄이는지 알기 위해, 아래에서 렌더링 과정을 간략하게 살펴보도록 하자.
- 3D 공간(x, y, z 축; z 축은 깊이를 나타낸다.)을 2D 화면(x, y 축)에 렌더링 하기 전에 Depth test를 진행한다.
- Depth buffer에 있는 값과 비교하여, 설정에 따라 depth buffer에 z-value(깊이 값)를 write 한다.
- Depth buffer를 참조하여 다른 fragment(pixel)에 의해 가려지는 fragment를 렌더링 하지 않는다(z-culling/depth-culling).
따라서, 3D widget material의 depth test를 비활성화하면 깊이 값과 상관없이 항상 렌더링 되는 것이다(비용은 살짝 더 증가하겠지만..).
진짜 간단하게 이야기해서 이런 건데, 개념 외에 원리는 나도 제대로 이해하지 못해서 시간 될 때 Learn OpenGL로 기초 그래픽스 지식을 쌓아가려고 한다. (수학과 영어가 굉장히 정말 엄청나게 중요하다는 사실을 다시 한번 깨닫습니다..)
Learn OpenGL, extensive tutorial resource for learning Modern OpenGL
Welcome to OpenGL Welcome to the online book for learning OpenGL! Whether you are trying to learn OpenGL for academic purposes, to pursue a career or simply looking for a hobby, this book will teach you the basics, the intermediate, and all the advanced kn
learnopengl.com
결과
위의 결과에 더해 조준 시 Zoom 되는 기능과 조준 상태에서 총을 놓았을 때 일반 상태로 전환되는 기능을 구현한 영상이다. Zoom은 단순하게 pawn 내 camera의 부모 컴포넌트 position을 이동시켜 구현했다.
배운 점
- 모든 조건을 만족하는 하나의 답을 찾으려고 하기보다는 각 조건에 맞는 답을 잘 섞을 생각을 하자.
- 무작정 내가 아는 범위 내에서 가설을 세우고 시도하려 하기보다는, 가장 먼저 자료 조사를 제대로 해보자.
- 고집부릴 거면 한 번이라도 해보고 고집부리자.
- 자료 조사를 할 거면 대충 훑어보고 아닌 것 같으면 넘기기보다는, 제목과 키워드 위주로 제대로 확인하자.
더 알아볼 것들
- Projection matriix
- frustum culling
- clip space
- OpenGL
참고 링크
- 언리얼 공식 문서 - 위젯 블루프린트
- 언리얼 공식 문서 - 머티리얼 프로퍼티
- Hangry Bunnies From Mars - VR UMG Widget UI Infront of Everything Depth Render
- Learn OpenGL - Depth Testing
- songho.ca - Projection Matrix
'개발 > 언리얼' 카테고리의 다른 글
언리얼 엔진으로 Cel Shading을 구현해보자. (8) | 2024.08.23 |
---|---|
언리얼 엔진으로의 원신 모델링 적용 기록 (실패) (2) | 2024.06.08 |
[Blueprint] 나이아가라 시스템에서 외부 데이터를 변수로 입력 받는 방법 (0) | 2024.01.10 |
[Blueprint] Linetrace (0) | 2024.01.09 |
[Blueprint] Timeline (0) | 2024.01.03 |