본문으로 바로가기
728x90
반응형

 

 

# UI 프레임 워크 구조 및 세부 구조 #

한눈에 보는 UI 프레임 워크!.... 내가 만들었지만 보기 어렵네..?

 

1. Frontend Developer Settings

  • UDeveloperSettings을 한다.
  • Config 파일 기반으로 UI Screen을 태그로 매핑함
  • “Frontend.Widget.OptionScreen” 같은 Tag → 위젯 Blueprint Class 매핑
  • 이것이 실제 UI Screen Factory 역할을 함
  • 어떤 Screen Tag가 어떤 위젯 BP를 가리키는지 저장
  • 게임 시작 시 / 화면 전환 시 UI Subsystem이 이것을 참고하여 로딩함

 

2. List Data Object 

  • 실제 옵션 값 저장
  • 값 변경 시 Delegate Broadcast
  • TryResetBackToDefaultValue() 등 다양한 함수 제공

3. ListEntry Widget

  • 각 옵션 항목 UI
  • UListDataObject를 UserObject로 받음
  • 슬라이더/콤보박스/버튼 등 실제 UI 조작 제공

 

4. Screen

  • UCommonActivatableWidget
    → 화면 활성화/비활성화(스택, 애니메이션, 입력 포커스)
  • UWidget_ActivatableWidget
    → 프로젝트 전용 Screen Base
    → 모든 화면 구조, UI Subsystem 연동, InputActionBinding 기본 제공
  • OptionScreen (옵션 메뉴)
  • ConfirmScreen (Yes/No 창)

 

# 델리게이트와 서브시스템 #

 

1. delegate(델리게이트)

1). 사전적 의미: 대리자

2). 언리얼에서 쓰임: 나중에 호출할 함수들을 저장해 두는 변수. 약간, 서버에서 브로드캐스팅을 해서 유저에게 뿌리는 거처럼 각각 델리게이트에 함수를 바인딩(AddObject) 해둔 함수들을 사방에서 빵빵 터트린다. 

3). 주요 함수 

  • AddObject(...) : 객체의 함수를 델리게이트에 등록한다. 
  • BroadCast(...) : 등록된 함수들 한 번에 다 호출한다. 

 

이번 UI 프로젝트에서 리셋 동작으로 델리게이트를 이해해보자.

🔸리셋 동작으로 알아보는 델리게이트🔸

1. ResetActionHandle을 받아오며, 액션에 실행될 함수를 등록한다. 

ResetActionHandle

2. 텝이 변경될 때, 텝에 보일 정보들 (UListDataObject_Base 또는 그의 자식)들에게 델리게이트를 등록한다. 

3. 텝에 보여질 정보들 (UListDataObject_Base 또는 그의 자식)들의 값이 변경될 때마다 함수를 실행했고, 그 함수는 최상의 클래스 UListDataObject_Base에서 OnListDataModified를 BroadCast 한다. 

4. BroadCast를 하게 되면 AddUObject에 Bind 한 함수가 실행되게 된다. 변경된 값이 디폴트값과 다르다면 TArray <UListDataObject_Base*> ResettableDataArray 리셋할 수 있는 객체를 AddUnique(중복을 피하는..) 넣어준다. 

그 배열(  ResettableDataArray)이 비어 있지 않으면 위에서 핸들로 받아둔 ResetActionHandle이 Screen상으로 보일 수 있도록 AddActionBinding 해준다. 비어 있다면 RemoveActionBinding 해준다. 

5. ResetAction의 버튼을 눌러 액션을 취하게 되면 저장해 둔 델리게이트 함수가 실행이 되고, ResettableDataArray 배열에 들어 있는 UListDataObject_Base의 초기화 함수를 실행시켜 리셋시켜 준다. 

 

 

2. 서브시스템 Subsystem -> UGameInstanceSubsystem 

1). 언리얼에서 쓰임:  싱글톤 패턴 대신 언리얼 스타일로 만든 전역 매니저, 게임 전체에서 공통으로 쓰는 UI 인프라등을 전역으로 관리하는 시스템!

 

2) 서브시스템 종류

  • UEngineSubsystem : 엔진 전체에서 하나
  • UGameInstanceSubsystem : 게임 인스턴스당 하나 
  • UWorldSubsystem : 월드마다 하나 (맵마다)
  • ULocalPlayerSubsystem : 로컬 플레이어마다 하나

 

🔸현재 프로젝트에서 사용한 서브 시스템 🔸

PrimaryLayout를 하나 들고 있으면서 위젯 스택을 찾아 위젯을 비동기로 로딩하고 푸시한다. 

확인 창과 같이 공통 UI 패턴은 전용 헬퍼 함수로 캡슐화한다. 

 

3) 흐름 정리

1.  버튼 위에 마우스 오버하면,  UFrontendCommonButtonBase::NativeOnHovered() 실행한다. 

2. 오버로딩한 함수를 실행하게 되면, 서브시스템에 등록해 둔 델리게이트로 버튼이 들고 있는 DescriptionText

FrontendUISubsystem::OnButtonDescriptionTextUpdated.Broadcast(this, DescriptionText)로 전파(Broadcast) 한다.

3. WBP_TEXT_Button_Description (블루프린트)에서 위젯이 초기화 (OnInitialized) 될 때 Subsystem의 Delegate에 바인딩해 두었는데, 2번으로 인해 바인딩해둔 델리게이트가 실행이 된다.

 4. 델리게이트가 호출되면 Description Text Widget이 Description 문자열을 갱신(SetText)한다.

 

이는 정확하게 Subsystem → 전역 이벤트 허브 / Broadcast 중심 UI 구조를 사용하고 있다.

 

4) 장점 정리 

위 과정을 통해 위에서 사용한 ( GameInstanceSubsystem ) 서브시스템의 장점을 정리해 보자. 

1. "직접 참조"가 필요 없음 (완전한 Decoupling)

  • Button    → Broadcast
  • Subsystem → 전달만
  • TextWidget → 델리게이트 구독

버튼은 TextWidget 존재 여부를 모름
TextWidget은 버튼이 몇 개 있는지도 모름
서로 모르는 상태에서 Subsystem을 통해 “메시지 방식”으로 연결됨

2. UI 전역 이벤트 관리 가능함 GameInstanceSubsystem이 제일 알맞다. 

3. 레벨 전환해도 살아았다. GameInstanceSubsystem의 강력한 장점 

  • 옵션 창
  • 설정 저장/불러오기
  • 공통 팝업(Confirm, Error)
  • 공통 Description Text
  • 메인 레이아웃 관리

이런 것들은 레벨이 바뀐다고 사라지면 안 된다. GameInstanceSubsystem은 레벨 전환과 관계없이 유지되기 때문에
UI 시스템을 넣기 정말 좋은 위치이다. 

 

 

 

일 댕기면서 만드는데 1달 넘게 걸리고 이해하는데 3주 넘게 걸린 거 같다.. ^^ 

그래도 만족스럽다 전투 게임 씬도 있는데 그것도 정리하고 이해하고 영상 찍으려면 2주는 걸리겠죠..? 

그럼 다음에 또... 

 

출처

🔹그림 : 모두 직접제작 
🔹ChatGpt에게 많이 물어보면서 글 작성 openai.com/chatgpt
🔹강의: udemy ->
Create AAA Frontend UI/Menu Experience in Unreal Engine 5 using C++ and Common UI 

 

728x90
반응형