관리 메뉴

가끔 보자, 하늘.

언리얼 엔진 5.3 예제로 찍먹하기-03 Lobby 본문

개발 이야기/개발툴 및 기타 이야기

언리얼 엔진 5.3 예제로 찍먹하기-03 Lobby

가온아 2023. 11. 27. 10:41

이 샘플에는 총 4개의 Level이 있는데 아래와 같습니다.

  • M_Mainmenu : 멀티 플레이 메뉴. 호스트로 선택 후 싱글 플레이 하거나 조인할 유저 기다렸다가 멀티 게임하기
  • M_Lobby : 게임 시작 전 대기실. 캐릭터 및 맵 선택 메뉴
  • M_Demo, M_Demo2 : 게임 플레이 레벨

찍먹 중이라 싱글 플레이 부분만 검토해 볼 예정이라 M_Mainmenu는 건너띄겠습니다. 오늘은 바로 M_Lobby를 알아보겠습니다.

 

툴 화면. 중앙 4개의 객체는 멀티 플레이 시 최대ㅣ 4인의 캐릭터를 배치하는 포인트입니다. 

 

 

 

실행된 화면. 테스트 하느라 이미 모든 캐릭터를 개방한 상태입니다. 처음 실행했다면 왼쪽 캐릭터 리스트의 색이 다르게 나오고 구매 가격이 같이 출력됩니다. 

 

 

 

실행되면 왼쪽 화면처럼 노락색으로 보이는 객체들이 있습니다. 이를 게임이 실행되면서 동적으로 생성된 객체들이며, GameMode 혹은 여러 BP들에 의해 실행된 것들입니다.

 

저처럼 오래전부터 직접 게임을 처음부터 만드셨던 분들이나 (심지어) Unity로 게임을 개발하셨던 분들도 언리얼을 살펴보면 조금 이상한 점들이 눈에 띄었을 것입니다.

게임 실행 전 Outliner를 보면 Level 기본 Lighting과 스테이지를 구성하는 Cube, Plane 그리고 조인한 플레이어의 위치를 지정한 4개의 객체만 보이고 게임 상태를 관리하는 어떤 객체도 보이지 않기 때문입니다. (언리얼에서는 이런 기본적인 객체를 액터라고 부르는 듯 합니다. 확실하지는 않지만.. ^^a 여기서는 이런 모든 액터들을 통칭할 수 있는 객체로 그냥 부르겠습니다.)

언리얼에는 "GameMode(게임 모드)"라고 명시된 메뉴가 있습니다.  (게임 모드와 게임 스테이트 관련 공식문서 링크)

게임 모드란 "게임의 규칙을 결정하고 정보를 처리하는 액터"라고 명시되어 있습니다. 이는 게임의 기본 규칙을 정의하며, 게임이 시작될 때 가장 먼저 초기화되고 실행되는 액터입니다. 또한  "Player Controller", "HUD", "Game State" 등 다른 기본 액터들을 생성하고 이런 액터들은 게임의 전반적인 흐름을 제어하고, 사용자 인터페이스, 게임의 상태, 플레이어의 입력 및 제어 등을 관리하게 됩니다. 아래 메뉴에서 설정할 수 있으며 이 액터는 BP class 생성 시 Game Base Mode를 부모로 선택하여 생성할 수 있습니다.

게임 모드에는 다음과 같은 설정이 가능합니다.

  • Default Pawn Class : 기본 플레이어 캐릭터. https://docs.unrealengine.com/5.3/ko/pawn-in-unreal-engine/ 의 default pawn 참고.
  • HUD Class : Heads-up Display 은 아니고 ^^a 화면에 오버레이된 엘리먼트를 표시하기 위한 베이스 오브젝트입니다.
  • Player Controller Class (추측 : 플레이어 컨트롤 관련 클래스)
  • Spectator Class (추측 : 관전자??)
  • Game State Class : 멀티 플레이 시 전체 유저가 공유할 상태 정보를 관리
  • Player State Class :  로컬 플레이 유저의 상태 정보
  • Game Session Class : (추측 : 멀티 플레이 시 세션 관리 클래스)
  • Replay Spectator Player Controller Class : (추측 : 게임 리플레이 할 때 관전자 모드에서의 컨트롤)
  • Server Stat Replicator Class : (추측 : 멀티 플레이 시 서버 상태 복제-브로드케스팅에 쓰일 것 같은- 클래스)

각 클래스의 쓰임새를 알아보려 https://docs.unrealengine.com/5.3/ko/ 에서 검색해봐도 나오질 않네요. 아마 다른 문서에는 상세히 기록되어 있을 듯 하지만 여기서는 그냥 넘어가겠습니다. (...)

그럼 이 샘플 의 Lobby에서는 GameMode가 어떤 역할을 하는지 살펴보겠습니다.

BP_Lobby_GameMode -> BP_Base_GameMode -> AGameModeBase

BP_Lobby_GameMode의 Event Graph를 살펴보면 EventOnPostLogin 에서 접속한 유저의 정보를 서버내 다른 플레이어에게 전달하는 역할을 하고 있습니다.

두 개의 지역함수(언리얼에서는 쓰는 용어는 아닐 수 있습니다. 이 BP Class 내에서만 사용되는 함수라는 의미입니다.)를 포함하고 있고 UpdateLobbyUI(접속한 유저수 표기), UpdateClassNames(접속한 유저 이름 표기)가 있으며 모두 EventOnPostLogin에서 호출되는 것을 확인할 수 있습니다.

(* 만약 새로운 함수를 추가하고 싶다면 (1)번 버튼으로, 부모 BP Class의 함수를 override해 기능을 확장/변경하려면 (2)번 버튼을 눌러 override할 함수를 선택하여 구현할 수 있습니다.)

여기까지만 보면 아직 로비 레벨을 직접적으로 관리하는 코드는 없다고 보여지네요. Widget(UI)들을 관리하는 코드도 안보이네요.

그런데 Details 패널의 Classes를 보면 기본 클래스 중 Player Controller Class와 Defailt Pawn Class가 설정된 것을 확인할 수 있습니다.

BP_Lobby_PlayerController의 Event BeginPlay에서 해당 캐릭터가 로컬 플레이어라면 자신의 화면 UI를  생성하도록 합니다. UI를 캐릭터 클래스에서 생성, 관리하는게 좀 생소하긴 하지만 그렇다고 합니다. 

BP_Lobby_Character는 BP_Base_Character를 상속받습니다. 참고로 BP_Base_Character 클래스는 인게임에서 사용하는 클래스입니다. 생성 시 캐릭터 데이터를 로딩하여 이름을 출력하는 역할을 하는군요. 실제 랜더링 할 객체 정보도 있으니 Components도 확인해 보세요. 

Widget 관련해서 유니티에서는 에디팅 모드에서도 맵에 배치하고 바로 볼 수 있는 반면 언리얼엔진에서는 Widget BP에서 로컬 좌표계로만 수정, 편집 할 수 있습니다. (이게 의외로 좀 답답하긴 하더군요. 혹시 에디터에서 3D 액터들과 동시에 보면서 편집하는 방법 아시는 분은 댓글 부탁드리겠습니다.)

이제 게임을 실행하면 BP_Lobby_GameMode에 등록된 BP_Lobby_PlayerController , BP_Lobby_Character들의 인스턴스가 생성되고 각 생성된 인스턴스가 데이터 로딩 및 UI를 생성한다는 사실을 알게 되었습니다.

마지막으로 Widget에 대해 정리하고 마무리 하도록 하겠습니다. 

WB_LobbyMenu은  로비에서 Client로 조인한 유저 리스트, 그리고 자신이 구매 혹은 선택 가능한 캐릭터 리스트, 플레이할 맵을 선택하는 UI가 구현되어 있습니다. 

(1)은 선택 가능한 캐릭터 리스트가 출력되고
(2)에서는 맵을 선택할 수 있습니다. 이 데모에서는 M_Demo와 M_Demo2를 선택할 수 있습니다.
(3) 버튼을 누르면 게임이 시작됩니다.

WB_LobbyMenu 를 열어보면 Widget 관리 윈도우가 열리는데 기본적으로 Designer로 선택되어 있습니다. 여기서는 사용할 각종 컨트롤들을 편집할 수 있습니다.

로비 화면의 UI는 위와 같이 구성되어 있습니다. 

  1. 선택 가능한 캐릭터 리스트가 출력. 수집 전 캐릭터는 구매 가능한 골드가 표시됩니다.
  2. 맵 선택. 이 데모에서는 M_Demo와 M_Demo2를 선택할 수 있습니다.
  3. 버튼을 누르면 게임이 시작됩니다.

다음으로 Graph 버튼을 눌러 blueprint 내용을 살펴보겠습니다.

Event Construct 에서는 플레이어 데이터를 확인하여 Gold 표기 및 (1)에 들어갈 캐릭터 리스트를 설정하고 Host일 경우 Select Map과 Launch Game 버튼 활성화를, Client일 경우 준비완료 버튼을 보여줍니다. Host 판별을 "isServer"라는 함수를 통해 확인하는데 이는 언리얼 엔진의 네트웍 모듈의 기본 함수인 듯 하네요.Host나 혹은 싱글 게임일 경우 isServer 함수는 true값을 리턴합니다.

On Clicked(Button_Launch) 이벤트가 발생하면 LoadingScreen을 보여주고 유저가 선택한 맵을 로딩합니다. 이를 수행하기 위해 ServerTravel이라는 네트웍 관련 내장 함수를 호출합니다. 추후 네트웍 부분을 정리할 기회가 생기면 다시 상세히 정리해 보겠습니다.

이렇게 Lobby까지 간단히 살펴보았습니다. 다음 글에서 게임 플레이까지 살펴보고 마무리하겠습니다. :)

반응형