개별 창 방식에서 통합 플레이어 메뉴 방식으로 변경했다.


통합 메뉴 구조 설계

새로 만든 위젯 : WBP_PlayerMenu

이 위젯은 플레이어가 Tab 키를 눌렀을 때 열리는 메뉴이다.

구조는 크게 두 부분으로 나누었다.

  • 상단: 인벤토리, 제작, 스킬, 옵션 버튼
  • 하단: 선택한 탭에 맞는 실제 UI 내용

하단 영역에는 WidgetSwitcher를 사용했다. WidgetSwitcher는 여러 개의 위젯을 자식으로 가지고 있다가, 현재 선택된 인덱스의 위젯만 보여주는 역할을 한다.

Inventory    = 0
FactoryCraft = 1
SkillTree    = 2
Option       = 3

즉, 인벤토리 버튼을 누르면 WidgetSwitcher의 인덱스를 0으로 바꾸고, 제작 버튼을 누르면 1로 바꾸는 방식이다. 이렇게 하면 실제로는 WBP_PlayerMenu 하나만 열린 상태에서 내부 내용만 바뀌게 된다.


게임 일시정지 처리

플레이어 메뉴가 열려 있는 동안에는 게임이 진행되지 않도록 일시정지도 적용했다. 메뉴가 활성화될 때 게임을 멈추고, 메뉴가 닫힐 때 다시 풀어주는 방식이다.

SetGamePaused(World, true);

이 처리는 NativeOnActivated()에서 수행했다. Common UI 기반 위젯에서는 화면에 올라왔는지보다 “활성화되었는지”가 더 중요하기 때문에, 단순히 NativeConstruct()에서 처리하는 것보다 NativeOnActivated()를 사용하는 쪽이 자연스럽다.

닫힐 때는 NativeOnDeactivated()에서 퍼즈를 해제했다. 단, 이미 다른 이유로 게임이 퍼즈되어 있던 상황까지 마음대로 해제하지 않도록, 이 위젯이 직접 퍼즈를 걸었는지 여부를 따로 저장했다.


입력 문제 해결

작업 중 Tab 키와 ESC 입력이 서로 꼬이는 문제가 있었다. 메뉴를 닫았는데 다시 열리는 현상이 발생했는데, 원인은 IA_TogglePlayerMenu에 Pressed와 Released 트리거가 둘 다 들어가 있었기 때문이다.

Tab을 누르는 순간 Pressed가 실행되어 메뉴가 열리고 게임이 퍼즈되었다. 이후 Tab을 떼는 Released 입력이 퍼즈 상태에서 밀렸다가, ESC로 메뉴를 닫고 퍼즈가 풀린 뒤 뒤늦게 처리되면서 메뉴가 다시 열리는 문제가 생겼다.

그래서 메뉴 열기 입력은 Pressed만 남기고 Released는 제거했다.

메뉴 입력 설정은 다음처럼 정리했다.

IA_TogglePlayerMenu
- Key: Tab
- Value Type: Digital
- Trigger When Paused: true
- Trigger: Pressed
- Released 제거

또한 메뉴가 열린 상태에서 Tab 키를 눌렀을 때 버튼 포커스가 다음 버튼으로 이동하는 문제도 있었다. 이는 UMG의 기본 키보드 내비게이션 때문에 발생한 것이다. 버튼의 Is Focusable을 꺼서 Tab 키가 버튼 선택 이동에 사용되지 않도록 처리했다.


정리

이번 작업을 통해 UI 구조를 개별 창 중심에서 통합 메뉴 중심으로 변경했다.

기존 방식은 인벤토리, 제작, 스킬 창을 각각 따로 열고 관리해야 했다. 하지만 이제는 WBP_PlayerMenu 하나만 열고, 내부 WidgetSwitcher를 통해 탭을 전환하는 방식으로 바뀌었다.

이 구조의 장점

  • 메뉴 열림 상태를 하나의 위젯 기준으로 관리할 수 있다.
  • 탭 전환 로직이 단순해진다.
  • ESC 처리와 일시정지 처리를 한 곳에서 관리할 수 있다.
  • UI가 추가되어도 새로운 창을 따로 여는 대신 탭만 추가하면 된다.
  • 입력 충돌 문제를 줄일 수 있다.

결과적으로 플레이어 메뉴의 구조가 더 명확해졌고, 앞으로 옵션, 지도, 장비 같은 UI를 추가할 때도 같은 방식으로 확장할 수 있는 기반을 만들었다.