UMG
언리얼의 UI 시스템은 언리얼 모션 그래픽(Unreal Motion Graphics) 또는 UMG라고 합니다. 이는 Unity의 표준 uGUI 시스템과는 매우 다릅니다. Unity의 UI Toolkit UI Builder로 작업해 보신 분이라면, UMG의 UI 디자이너 제작 툴은 이와 가장 비슷하다고 보면 됩니다. UI 디자이너는 공식 문서에 자세히 설명되어 있으며, 특히 UI 제작하기 및 UMG 모범 사례 페이지는 언리얼 엔진으로 전환하는 Unity 개발자에게 유용합니다. UMG의 핵심은 위젯입니다. 위젯은 유저 인터페이스를 구성하는 데 사용할 수 있는 일련의 사전 제작된 함수와 계층구조입니다.
범용 UI
범용 UI(CommonUI)는 에픽게임즈에서 만든 자체 플러그인으로, 패럿에서 사용됩니다. 범용 UI는 보통 반복적으로 수동 설정하느라 시간이 오래 걸리는 '공통' 스타일과 액션을 위젯 전반에 걸쳐 구성해 줍니다. 실질적인 예로는 입력 디바이스 변경을 탐지하여 화면에서 입력 아이콘을 자동으로 전환하는 기능을 들 수 있습니다. 이 작업을 수동으로 수행하려면 시간이 오래 걸리지만, 범용 UI는 이 프로세스를 자동화합니다. 범용 UI는 향상된 입력의 키 리매핑 지원에도 필요한데, 자세한 내용은 향상된 입력 문서에서 확인할 수 있습니다.
범용 UI를 구성하려면 먼저 플러그인 창에서 활성화해야 합니다. 메뉴의 편집(Edit) > 플러그인(Plugins)에서 'Common UI Plugin'을 검색하여 활성화한 다음, 에디터를 재시작합니다.
프로젝트 세팅(Project Settings) > 일반 세팅(General Settings)으로 이동하여 게임 뷰포트 클라이언트 클래스(Game Viewport Client Class)를 'GameViewportClient'에서 'CommonGameViewportClient'로 변경합니다. 이렇게 하면 범용 UI 위젯이 엔진으로부터 입력 이벤트를 수신할 수 있습니다.
프로젝트 세팅(Project Settings) > 일반 입력 세팅(Common Input Settings)에서 향상된 입력 지원 활성화(Enable Enhanced Input Support) 체크박스를 선택합니다. 이렇게 하면 향상된 입력(Enhanced Input)이 일반 입력(CommonInput)과 함께 작동할 수 있습니다. 일반 입력은 범용 UI 위젯 내부의 입력을 처리합니다.
마지막으로, 프로젝트의 일부 모듈을 코드에서 사용할 수 있도록 활성화해야 합니다.
ProjectName.Build.cs파일(이 경우Parrot.Build.cs파일)로 이동합니다. PublicDependencyModuleNames 목록에 다음을 추가합니다.CommonInputCommonUIEnhancedInputGameplayTagsUMG
패럿 전용 위젯 계층구조
패럿에서 가장 먼저 살펴볼 UI 클래스는 AParrotHUD입니다. 언리얼 엔진의 HUD 클래스는 각 로컬 플레이어를 위해 생성되는 액터로, 헤드업 디스플레이를 처리합니다. HUD 클래스에는 직접 그릴 수 있는 캔버스와 디버그 캔버스가 있습니다. 이 클래스를 게임 모드 환경설정의 일부로 지정할 수도 있습니다. 패럿에서는 이 클래스가 모든 위젯이 생성되고 관리되는 루트 위젯을 소유하는 액터로 사용됩니다.
이 소유 위젯의 클래스 타입은 UParrotGameLayout입니다. UParrotGameLayout은 다른 모든 UI 위젯을 위한 C++ 베이스 위젯 컨테이너입니다. 그 안에는 UCommonActivatableWidgetContainerBase 타입의 '레이어' 목록이 있습니다. 표시하려는 다른 모든 위젯은 이 레이어 중 하나에 푸시됩니다.
패럿에서 구성된 베이스 레이어는 다음과 같습니다.
Game: UMG HUD 위젯을 푸시하는 레이어입니다.
GameMenu: HUD 상단에 표시할 위젯을 푸시하는 레이어입니다.
Menu: 일시정지 화면, 세팅 화면, 인벤토리 화면 및 기타 비슷한 화면 등, 모든 화면 위젯을 위한 레이어입니다.
Modal: 모든 모달 팝업을 위한 레이어입니다.
레이어당 한 번에 하나의 위젯만 활성화됩니다. 여러 가지 화면 위젯을 'Menu' 레이어에 푸시할 수 있지만 마지막 위젯만 활성화되어 표시됩니다.
패럿에서는 위젯이 모두 공통 기능을 공유하고 Menu 레이어로 푸시되므로, 활성화 가능한 화면에 대한 클래스 계층구조도 생성했습니다. 클래스 계층구조는 다음과 같습니다.
이 구성을 사용하여 패럿의 모든 UI 화면을 생성합니다.
위젯 스타일링
범용 UI 플러그인과 화면 구성을 사용하여 위젯 스타일링을 시작할 수 있습니다. Content/UI/Widgets/Common 아래의 W_ButtonBase는 살펴보기에 좋은 예시입니다. Content/UI/Styling 아래의 ButtonStyle_Base 스타일링 데이터를 사용하며, 범용 UI의 UCommonButtonStyle 클래스를 사용합니다. 커스터마이징할 수 있는 다양한 옵션이 있습니다. 예를 들면, 버튼 상태에 따라 사운드와 브러시를 커스터마이징할 수 있습니다. 이와 같이 범용 UI에는 사용 중인 위젯에 따라 다양한 스타일링 클래스가 있습니다. 커스터마이징이 필요한 경우, 이러한 스타일링 위젯의 엔진 코드를 참조하는 것이 좋습니다.
로딩 화면
패럿의 로딩 화면은 에픽게임즈의 자체 플러그인인 CommonLoadingScreen을 사용합니다. 이 플러그인을 실제로 사용하는 또 다른 예시는 에픽게임즈의 라이라(Lyra) 샘플 프로젝트에서 확인할 수 있습니다. 이 플러그인을 사용하는 이유를 이해하려면, 먼저 언리얼 엔진 레벨 로딩의 기초를 이해해야 합니다.
UE에서 레벨 로딩을 처리하는 방법은 몇 가지가 있습니다. 간단한 접근 방식은 블루프린트에서 Open Level 노드를 호출하는 것입니다. 이 함수는 맵에 대한 스트링 또는 소프트 오브젝트 레퍼런스를 통해 맵을 로드할 수 있습니다. 이 방식은 간단한 맵에는 잘 작동하지만, 주의할 점이 있습니다. 이 함수를 호출하면 맵이 동기식으로 로드되므로 새 맵에 로드해야 하는 데이터의 양에 따라 눈에 띄는 끊김 현상이 발생할 수 있습니다. 여기서 또 다른 문제는 뷰포트에 추가된 위젯이 이전 레벨에 존재하는 플레이어 컨트롤러에 연결되어 있다는 것입니다. 이는 레벨 전환 시 레벨 언로딩의 일부로 클린업됩니다.
맵에 따라 새로운 게임 모드를 로드하는 것이 유용할 수 있습니다(예: 싱글 플레이어 레벨 대 멀티플레이어 레벨). 하지만, Open Level 사용 시 발생할 수 있는 잠재적인 로딩 멈춤 현상을 피하면서 로딩 화면을 유지하려면 어떻게 해야 할까요? BP_ParrotGameInstance를 살펴보겠습니다.
여기서 비동기식으로 레벨을 로드하면 Open Level이 호출될 때까지 에셋이 준비되지 않는 문제를 해결할 수 있습니다. 코멘트에서 언급했듯이 로딩 화면 작업도 이미 여기서 처리됩니다. 플러그인 환경설정은 간단하며 편집(Edit) > 프로젝트 세팅(Project Settings) > 일반 로딩 화면(Common Loading Screen)에서 로딩 화면 위젯을 설정할 수 있습니다.
또한, 여기에 있는 디버깅 토글도 주의 깊게 살펴보세요. 이러한 에디터 내 테스트를 통해 패키지로 만든 버전에서의 로딩 화면 작동 방식을 더 잘 파악할 수 있습니다.
이제 로딩 화면과 함께 레벨이 로드됩니다. 싱글 플레이어와 멀티플레이어 레벨 순서를 구성하는 방법을 알아보려면 BP_ParrotGameInstance를 직접 살펴보는 것이 좋습니다. 게임 스테이트 구성은 언리얼 게임플레이 프레임워크 문서에서 다룹니다.