언어:
페이지 정보
엔진 버전:
언리얼 엔진

멀티플레이어 슈팅

언리얼 엔진

MultiplayerExample_Header.png

Simple Blueprint Multiplayer (간단한 블루프린트 멀티플레이어) 쇼케이스는 블루프린트UMG UI 로만 만들어진 게임으로, 블루프린트의 Session 노드를 사용하여 멀티플레이어 게임을 만드는 법에 대한 예제입니다. 메인 메뉴, 서버 리스트, HUD 에 점수판이 포함된 단순한 맵이 들어있습니다. 메인 메뉴에서 Play 를 클릭하면 세션을 호스팅하고 게임플레이 맵을 로드합니다. 그 후 다른 플레이어가 Find games 를 클릭하면 새로운 메뉴 화면에 호스팅되는 모든 게임 목록이 보이며, 그 중 하나를 클릭하면 참가 시도합니다. 오류가 있는 경우, 대화창이 표시되고 사용자는 메인 메뉴로 돌아갑니다.

이 게임은 GameInstance 블루프린트를 사용한 스테이트 관리 방법에 대한 예제가 되기도 합니다. GameInstance 는 이 작업을 하기 편리한 곳으로, 다른 맵이 로드되어도 유지되며, 오류 이벤트를 받는 오브젝트이기도 하기 때문입니다. 이 샘플 게임 내 대부분의 세션 호출 및 메뉴 전환은 GameInstance 에서 처리됩니다.

현 상태에서 이 문서에 다룰 것은 멀티플레이어 게임 호스팅, 발견, 참가, 종료에 대한 온라인 세션 노드 및 그 구현입니다. 나중에 다른 플레이어에게 발사하여 맞추기, 사망/리스폰, 점수 획득 등의 게임플레이적인 면을 반영하도록 업데이트하겠습니다.

게임 시작/플레이

여기서는 게임 자체를 시작 및 플레이하는 법을 알아보고, 게임의 컴포넌트에 대해 분석해 보겠습니다.

언리얼 엔진 4 안에서의 멀티플레이어 테스트가 처음이신 분들은, 멀티플레이어 테스트 문서를 먼저 검토해 보는 것이 좋습니다.

게임을 로드하려면:

  1. Game/Maps 폴더의 MainMenu 맵을 엽니다.

  2. MainMenu 맵을 열고서 플레이 버튼 옆 아래 화살표를 클릭한 다음 플레이어 수 를 2 로 설정합니다.

    SettingNumberOfPlayers.png

    데디케이티드 서버 실행** 옵션은 서버 리스트가 정상 표시되지 않는 문제가 생길 수 있으며, 문제 해결중입니다.

  3. 플레이 버튼을 클릭하여 게임을 실행합니다.

  4. 게임이 실행되면 다음과 같은 화면이 뜹니다.

    twoWindows.png

    _위에서는 각각 **640x480** 으로 설정된 **새 에디터 창** 에서 플레이중이며, **고급 세팅...** 옵션에서 설정할 수 있습니다.

    네트워크 테스트를 하면서 위와 같은 로컬 멀티플레이어 게임이 아닌 경우, 독립형 플레이 모드 를 사용하여 게임에 참가하거나 다른 이가 자신의 호스팅 게임에 참가하도록 하세요. PIE (에디터에서 플레이 모드)를 통한 네트워크 게임 실행은 현재 불안정하여 처리중에 있습니다.

메인 메뉴를 나눠보면 아래와 같습니다.

MainMenu.png

옵션

설명

1

현재 게임 창에서 게임을 시작 및 호스팅합니다.

2

참가할 게임을 선택할 수 있도록 모든 활성 게임이 나열되는 서버 리스트 화면을 표시합니다.

3

게임을 종료합니다.

4

접속 모드를 게임 모드와 인터넷 게임 모드를 전환합니다.

게임을 호스팅 또는 참가하도록 선택한 이후에는, 아래와 같은 게임플레이 영역에 들어서게 됩니다.

InGame1.png

화면 좌상단 구석(노랑 박스 부분)에 플레이어 캐릭터의 이름 텍스트가 보일 것입니다. 플레이어 캐릭터 이름 오른쪽의 초록 박스는 현재 점수입니다. 플레이어가 게임이 참가함에 따라 좌상단의 박스가 게임 내 현재 플레이어 수와 그 점수를 반영하도록 업데이트될 것입니다.

TwoInGame.png

위 그림에 나타난 플레이어 이름은 현재 랜 게임을 나타내고 있습니다. Steam 같은 서비스 사용시, 그 대신 플레이어의 Steam 이름이 여기에 표시될 것입니다.

게임을 호스팅한 이후, 둘째 플레이어에서 Find games 버튼을 누르면 서버 리스트 가 표시됩니다.

ServerListWindow.png

잠깐 게임 검색 이후, 현재 활성 게임이 목록에 표시됩니다. 이 창에서 왼쪽에서 오른쪽 순으로 서버 이름, 게임에 있는 플레이어 수, 게임 세션의 현재 핑이 표시됩니다. 화면 좌하단 구석의 Refresh 버튼을 클릭하면 리스트가 업데이트되며, Back 버튼을 클릭하면 메인 메뉴로 돌아갑니다. 목록에 있는 이름을 클릭하면, 그 서버에 참가 및 게임에 스폰 시도합니다.

게임에 들어서면, 왼쪽 마우스 버튼 을 클릭해서 준비 신호를 보내야 합니다.

1Ready.png

준비 상태로 클릭하면 (서버 또는 클라이언트), 화면 좌상단에 텍스트가 표시되어 플레이어가 준비되었음을 알립니다.

준비 완료 후 아래 컨트롤을 사용하여 게임을 플레이할 수 있습니다.

컨트롤

설명

오른쪽 마우스 버튼

무기를 겨눕니다 (누르고 있으면 겨누는 상태가 유지됩니다).

마우스

마우스를 움직이면 무기 조준이 가능한 조준 모드 로 들어갑니다.

왼쪽 마우스 버튼

무기를 발사합니다.

마우스 휠 (휠 위/아래)

조준 모드가 아닐 때 재장전합니다.

Q

게임내 일시정지 메뉴를 띄웁니다 (재개 또는 게임 종료)

게임의 목적은, 다른 플레이어를 쏴 맞추면 점수를 획득하여 다른 플레이어가 리스폰되도록 할 수 있습니다. 각 플레이어마다 6 발이 주어지며, 마우스 휠 (휠 위/아래) 로 (하나씩) 재장전 가능합니다.

프로젝트 셋업/환경설정

여기서는 콘텐츠 브라우저 에서 생성( 또는 변경)된 애셋 각각을 그 역할과 함께 다룹니다. 다수의 블루프린트와 UMG UI 애셋은 서로 통신( 또는 의존)하므로 이 프로젝트를 처음부터 새로 만들려 한다면, 필요한 애셋 각각을 만든 다음 나중에 채워넣는 것이 좋습니다.

각 애셋은 콘텐츠 브라우저 내 각 폴더에서 찾을 수 있습니다:

Game/Blueprints/Widgets

이름

설명

ErrorDialog

발생하는 오류 메시지를 표시하는 UI 화면입니다.

HUD

모든 플레이어 이름과 점수가 들어있는 ScoreboardRow 위젯이 표시되는 게임내 점수판입니다.

InGameMenu

플레이어가 게임을 나가 메인 메뉴로 돌아갈 수 있도록 하는 게임내 메뉴입니다.

LoadingScreen

게임 참가 시도시 나타나는 간단한 로딩 화면입니다.

MainMenu

게임 실행시의 메인 메뉴입니다. 플레이어가 게임을 호스팅, 참가, 종료할 수 있습니다.

ScoreboardRow

이 위젯은 HUD 에 추가되며 플레이어의 이름과 점수가 포함됩니다.

ServerList

참가할 수 있는 모든 게임이 표시되는 ServerRow 위젯 목록이 들어가는 메뉴입니다.

ServerRow

서버 이름, 플레이어 수, 핑 정보가 포함된 활성 서버 관련 데이터 각각의 열이 저장된 위젯입니다. ServerList 위젯에 전달됩니다.

Game/Blueprints

이름

설명

MyGameInstance

(인스턴스 블루프린트) - 메인 메뉴 및 하위 화면과 게임플레이를 오가는 모든 전환 상태는 물론 오류 이벤트를 처리합니다.

MyGameMode

(게임 모드 블루프린트) - 모든 디폴트 클래스(Pawn, HUD, PlayerController, ...)를 담습니다. 또한 플레이어 리스폰 및 플레이어가 게임플레이 세션에 처음 참가했을 때 벌어지는 일도 처리합니다.

MyPlayerController

(플레이어컨트롤러 블루프린트) 게임내 UI 를 구성하고 플레이어가 게임내 일시정지 메뉴를 열 수 있도록 합니다.

MyPlayerState

(플레이어스테이트 블루프린트) 각 플레이어의 점수를 처리합니다.

ProjectileBP

(액터 블루프린트) 플레이어끼리 서로 발사할 수 있는 프로젝타일이 대미지를 입힐 것인가 입니다.

State

(Enum) 게임이 처해있을 수 있는 모든 상태 목록입니다.

Game/Gunslinger

이름

설명

Gunslinger_BP

게임내 플레이 가능 캐릭터입니다.

GunslingerTTP

Gunslinger_BP 와 사용할 스켈레탈 메시입니다.

Gunslinger_AnimBP

Gunslinger_BP 에 대한 애니메이션을 돌리는 데 사용됩니다.

Game/Character

이름

설명

Character_Parent

(부모) Gunslinger_BP 에 사용되는 머티리얼입니다.

Character_Instance

(인스턴싱됨) Gunslinger_BP 와 사용되는 머티리얼입니다.

Game/Fonts

이름

설명

ScoreFont

Scoreboard 위젯에 추가되어 사용되는 폰트입니다.

Game/Maps

이름

설명

MainMenu

프로젝트/에디터 시작시 로드되는 디폴트 맵으로, 프론트 엔드 디스플레이가 들어있습니다.

Level_01

플레이어가 호스팅 또는 게임에 참가할 때 플레이어가 스폰되는 게임플레이 맵입니다.

환경설정 세팅

멀티플레이어 게임을 제대로 호스팅하거나 접속하기 위해서는, 다음과 같은 위치에서 찾을 수 있는 DefaultEngine.ini 파일에 세팅을 만들어 줘야 합니다: UnrealProjectDirectory/ProjectName/Config

ExampleLocation.png

연 이후에는 사용할 OnlineSubsystem 은 물론, 그 서브시스템에 해당하는 DefaultPlatformService 도 지정해 줘야 합니다.

예를 들어, OnlineSubsystemNull 를 추가하여 랜에서 플레이 가능합니다:

[OnlineSubsystem]
DefaultPlatformService=Null

아니면 OnlineSubsystemSteam 을 사용하여 Steam 을 통해서도 플레이 가능합니다:

[/Script/Engine.GameEngine]
+NetDriverDefinitions=(DefName="GameNetDriver",DriverClassName="OnlineSubsystemSteam.SteamNetDriver",DriverClassNameFallback="OnlineSubsystemUtils.IpNetDriver")

[OnlineSubsystem]
DefaultPlatformService=Steam

[OnlineSubsystemSteam]
bEnabled=true
SteamDevAppId=480
bVACEnabled=0

[/Script/OnlineSubsystemSteam.SteamNetDriver]
NetConnectionClassName="OnlineSubsystemSteam.SteamNetConnection"

Steam 을 사용한다면, 부가 SDK 및 INI 구성 이 필요하며, 자세한 내용은 링크를 참고하세요.

블루프린트 길잡이

여기서는 게임의 사양한 상태 각각을 안내해 드리면서, 그것을 구동하는 블루프린트를 살펴보겠습니다.

먼저 Startup 시퀀스를 살펴봅시다.

Startup

MainMenu 맵에 있을 때 레벨 블루프린트 를 엽니다.

Startup1.png

레벨 블루프린트 를 열고 보면, "Game Logic Starts Here" 라는 스크립트 부분이 보일 것입니다.

Startup2.png

게임 로직이 정말 이 스크립트 부분에서 시작하니, 뛰어난 코멘트입니다. 여기서는 게임이 시작되면, 게임 인스턴스를 구한 다음 MyGameInstance 블루프린트로 형변환시키고 있습니다. 그렇게 하면 그 안의 변수, 함수, 스크립트에 접근할 수 있으며, 여기서는 (아래와 같은) Begin Play Show Main Menu 라는 함수를 호출합니다.

Startup3.png

Begin Play Show Main Menu 가 호출되었을 때 처음 하는 일은, IsCurrentState 라는 이름으로 생성된 매크로를 실행하는 것입니다.

IsCurrentState 매크로

Startup4.png

IsCurrentState 는 (매크로 노드에 지정된) In State 가 (게임의 현재 상태를 저장하는 변수인) Current State 라는 변수와 동일한지 검사합니다. Current State 변수는 State 라는 이름의 Enum 을 사용하여 게임이 속할 수 있는 각 상태를 저장합니다.

Current StateIn State 와 같기에, ShowMainMenuEvent 커스텀 이벤트가 호출됩니다.

Startup5a.png

Startup5.png

ShowMainMenuEvent 가 처음 하는 일이 IsCurrentState 매크로 를 실행하여 Playing 에 대한 현재 상태를 검사, TrueMainMenu 레벨을 열지만, 게임이 현재 Startup 상태라 False 값을 반환합니다. 그러면 TransitionToState 라는 이름으로 생성된 다른 매크로를 호출합니다.

TransitionToState 매크로

TransitionToState 이하로 처음 하는 것은 IsCurrentState 매크로 (1) 를 실행하여 Current StateDesired State 를 비교한 다음, 같으면 화면에 오류를 출력합니다 (2). 서로 같지 않으면, Switch on State 노드를 실행(3)시켜 Current State 를 구한 다음 (가능한 경우 현재 표시중인 UI 위젯을 숨기는) Hide Widget 이라는 함수를 실행하거나, (호출하는 플레이의 세션을 소멸시키는) Destroy Session Caller 라는 커스텀 이벤트를 실행합니다.

Startup6.png

Switch on State 가 완료된 이후, 지정된 Desired State 가 반영되도록 Current State 가 업데이트됩니다.

TransitionToState 매크로 실행 이후, ShowMainMenuEvent 커스텀 이벤트를 계속할 수 있습니다.

Startup7.png

위에서 IsValid 노드가 (1) 실행되어 Main Menu 변수가 유효한지 검사하는데, 첫 실행에는 그렇지 않습니다 (그랬다면 위의 (2) 와 (3) 을 건너뛰었겠지요). Step (2) 은 Create Widget 노드를 사용하여 Main Menu 라는 UMG 위젯 블루프린트를 생성한 다음 변수로 승격 (3) 시켜 나중에 재생성할 필요 없이 접근할 수 있도록 합니다. (4) 에서 Set Input Mode UIOnly 노드를 사용하여 입력을 UI 에만 제한시키고, (5) 에서 Main Menu 위젯을 뷰포트에 추가시켜 메인 메뉴 화면을 표시합니다.

Startup8.png

다음으로 Play 버튼을 눌러 게임을 호스팅할 때 무엇이 벌어지는지 살펴보겠습니다.

게임 호스팅

메인 메뉴가 로드된 이후 Play 버튼을 클릭하면, MainMenu 위젯 블루프린트 안에서 다음의 스크립트가 실행됩니다.

Play1.png

OnClicked 이벤트는 MainMenu 위젯 블루프린트의 디자이너 탭에서 "Play" 버튼이라고 지정된 Button 에 해당합니다. 이 이벤트가 발동되면, 게임 인스턴스를 구한 다음 MyGameInstance 블루프린트로 형변환하여, 그 안에서 Host Game Event 라는 커스텀 이벤트를 호출할 수 있도록 합니다.

Play2.png

HostGameEvent 가 처음 하는 일은, MyGameInstance 블루프린트 안에서 ShowLoadingScreen 라는 커스텀 이벤트를 실행하는 것입니다.

Play3.png

ShowLoadingScreen 가 호출되면 Desired StateLoading Screen 으로 설정된) TransitionToState 매크로 를 실행시킵니다.

그런 다음 아래 IsValid 체크(1)를 실행하여 ShowLoadingScreen 이벤트를 계속합니다.

Play4.png

IsValidLoading Widget 이 유효한지 검사하는데, 처음에는 그렇지 않습니다 (그랬다면 위의 (2) 와 (3) 을 건너뛰었겠지요). Step (2) 는 Create Widget 노드를 사용하여 Loading Screen 이라는 UMG 위젯 블루프린트를 생성한 다음 변수로 승격(3)시켜 재생성할 필요 없이 접근할 수 있도록 합니다. (4) 에서 Loading Widget 을 뷰포트에 Add to Viewport 노드로 추가한 다음 Set Input Mode UIOnly 노드를 호출하여 (이 시점에서는 게임내 표시되는) 로딩 화면 도중 입력을 UI 로만 제한시킵니다.

Play5.png

Loading Screen 이 표시된 이후, 스크립트는 HostGameEventCreate Session 노드로 되돌아갑니다.

Play6.png

Create Session 노드에서, Public Connections (또는 세션에 참가 허용된 플레이어 수)가 4 로 설정되어 있습니다. Enable LAN 이라는 Boolean 변수도 있어 Use LAN 입력 핀에 연결되어 있습니다. 이 Enable LAN 변수는 메인 메뉴의 Paly Mode 토글과 함께 사용되는데, 나중에 설명하도록 하겠습니다. 세션이 성공적으로 생성되었으면, Open Level 노드를 사용하여 플레이 세션에 사용될 맵을 엽니다. 실패한 경우, OnFailure 핀을 실행하여 DisplayErrorDialog 라는 이름으로 생성된 매크로를 호출합니다.

DisplayErrorDialog 매크로

DisplayErrorDialog 매크로가 호출되면 먼저 (1) TransitionToState 매크로 를 실행하여 Error Dialog 상태로 전환합니다. 새로운 상태가 적용된 이후에는, Destroy Session Caller 라는 커스텀 이벤트를 호출(2), 현재 플레이어에 대한 세션을 소멸시킵니다 (이벤트 그래프에서 찾을 수 있습니다). 세션 소멸 이후 IsValid 엔진 매크로가 Error Dialog 라는 (실제로는 Error Dialog 위젯 블루프린트를 가리키는) 변수가 정말 유효한지 검사합니다.

Play7.png

첫 실행시 Error Dialog 는 유효하지 않으며, 그랬다면 아래 (1) 과 (2) 를 건너뛰고 (3) 으로 바로 갔을 것입니다.

Play8.png

하지만 첫 실행시, 위의 (1) 은 Create Widget 노드를 사용하여 ErrorDialog 위젯 블루프린트를 생성 및 실행합니다. (2) 에서 ErrorDialog 위젯 블루프린트가 Error Dialog 라는 변수로 승격됩니다 (이제 다음 번 이 매크로 실행시 사용 가능합니다). (3) 에서, ErrorDialog 위젯 블루프린트 내부에서 Set Message 함수가 호출되어 매크로 노드에 지정된 메시지를 구해온 다음 대화상자(아래 노랑 박스)에 표시할 메시지로 설정합니다. 반면 Add to Viewport (4) 는 화면에 Error Dialog 위젯 블루프린트를 표시하고, (5) Set Input Mode UIOnly 를 사용하여 입력 모드를 UI 전용으로 설정합니다.

Play9.png

에러 없이 Open Level 노드에 지정된 맵이 로드되어 플레이어가 게임플레이 에 들어옵니다.

게임 참가

메인 메뉴에서 Find games 버튼을 누르면 아래 MainMenu 위젯 블루프린트 안의 스크립트가 시작됩니다.

Findgames1.png

여기 OnClicked 이벤트는 MainMenu 위젯 블루프린트의 디자이너 탭에 "Find games" 버튼으로 지정된 Button 에 묶여 있습니다. 발동되면, 게임 인스턴스는 MyGameInstance 블루프린트로 형변환되어, 그 안에 접근하여 Show Server List Event 호출이 가능합니다.

Findgames2.png

ShowServerListEventTransitionToState 매크로 (1) 를 실행하는 것으로 시작하는데, 게임 상태를 Sever List 로 설정합니다. 거기서 Server List 위젯 블루프린트 변수를 대상으로 IsValid (2) 검사가 발생하는데, 유효하면 Add to Viewport (5) 노드를 사용하여 화면에 서버 리스트 메뉴를 표시합니다. 하지만 첫 실행시에는 Create Widget (3) 노드를 사용하여 서버 리스트 화면을 만들어야 하며, 그 후 변수로 승격 (4) 해야 화면에 표시됩니다. 화면이 표시되는 것으로 설정되었으면, Set Input Mode UIOnly 노드로 입력 모드를 UI 전용으로 설정합니다.

위에서 (5) 와 (6) 사이 실제로 서버 리스트 메뉴를 표시하는 도중에, ServerList 위젯 블루프린트 안에서 추가적인 스크립트가 실행되어 서버 리스트 메뉴를 활성 게임으로 채웁니다. 아래에서 보듯이 Server List 위젯 블루프린트 안에서는 Event Construct 노드가 사용 및 발동되어 위젯 블루프린트가 생성되도록 호출되면 즉시 RefreshListMacro 라는 이름으로 생성된 매크로를 실행합니다.

Findgames3.png

RefreshListMacro

RefreshListMacro 는 몇 가지 작업을 하는데, 그 첫 부분은 아래와 같습니다.

Findgames4.png

위에서 매크로가 호출되면, 먼저 하는 작업은 Refresh Button Enabled 라는 Boolean 변수를 False 로 설정(1)하여 Refresh 버튼을 꺼서 플레이어가 누르지 못하도록 합니다. 다음으로 Status Text 라는 변수를 Searching... (2) 로 설정하고 그 VisibilityVisible (3) 로 설정하여 Status Text 를 지닌 위젯을 업데이트하고 표시합니다.

(4) 에서 Found Session Widgets 라는 배열 변수는 서버 리스트를 채우는 데 사용되는 ServerRow 위젯 집합인데, 존재하는 각각은 Remove Child (5) 노드를 사용하여 제거합니다. 실제적으로 화면이 표시되면 나열할 서버를 제거하는 것입니다. (6) 에서 Found Session Widgets 변수도 비워 기존에 저장된 세션을 제거, 새로운 검색을 하기 전 모든 것이 말끔해 지도록 합니다.

다음, 매크로가 게임 인스턴스를 구해 Cast To MyGameInstance 노드(아래 1)를 사용하여 Enable LAN 이 True 인지 아닌지 알아봅니다 (세션 검색시 사용됩니다).

Findgames5.png

그리고 Find Sessions (2) 노드를 사용하여 존재하는 세션을 발견합니다 (Results 값으로 출력됩니다). 또 이 노드에서, Max Results (반환할 검색 결과 수)를 설정할 수 있습니다. Find Sessions 쿼리 결과가 Found Sessions (3) 라는 배열 변수에 할당 및 저장됩니다. 그런 다음 Branch (4) 를 통해 Results 를 검사하고, 0 이면 True (아니면, False) 핀을 실행합니다. 어떤 이유로든 Find Sessions 노드를 사용하는 데 실패했다면, OnFailure 이벤트를 호출하여 Search failed (5) 에 표시되는 Status Text 를 변경, 사용자에게 세션 검색이 완료되지 않았음을 알립니다.

Branch (이전 그림에서 4) 에서, True 면 (즉 찾은 세션이 없으면) Status TextNo sessions found (아래 7) 로 설정하고 Refresh Button Enabled 변수를 True (8) 로 설정하여 플레이어가 Refresh 버튼을 눌러 세션 검색을 다시 시도할 수 있도록 합니다.

Findgames6.png

세션을 찾았으면, Status Text VisibilityCollapsed (1) 로 설정하여 플레이어에게서 감춥니다. 그리고 ForEachLoop (2) 노드를 사용하여 찾은 Results 각각을 취한 다음, Create ServerRow (3) 노드를 사용하여 그 각각에 대해 Server Row Widget 을 생성합니다. 찾은 세션은 서버 리스트의 각 행이 됩니다.

(4) 에서, ServerRow 위젯 블루프린트 안에서 Set Search Result 함수를 호출하기 전, Found Session Widgets 배열에 Results 역시도 추가합니다 (ServerRow 위젯 블루프린트는 표시할 서버 이름, 플레이어 수, 핑 정보를 생성하는 데 사용됩니다). Set Search Result 노드로 ServerRow 위젯 블루프린트에 표시할 콘텐츠를 설정한 이후에는, Add Child (6) 노드를 사용하여 생성된 ServerRow 위젯 블루프린트 각각을 서버 리스트 메뉴에 표시되는 Scrolling Servers 스크롤 박스에 추가합니다.

찾은 세션 각각에 ServerRow 위젯을 생성하고 채워서 Scrolling Servers 위젯에 추가한 이후에는, ForEachLoop 가 완료되어 Referesh Button Enabled 변수가 True 로 (8) 설정됩니다.

RefreshListMacro 를 거쳐 세션을 검색한 이후, 찾은 세션은 Server List 메뉴에 표시됩니다.

Findgames7.png

Refresh 버튼을 클릭하면 RefreshListMacro 를 다시 실행하여 세션을 검색합니다. Back 버튼을 클릭하면 ShowMainMenuEvent 커스텀 이벤트를 실행합니다 (Startup 섹션에 소개되어 있습니다).

서버 리스트에 표시된 서버를 클릭하면, ServerRow 위젯 블루프린트에 OnClicked 이벤트를 발동합니다 (아래 참고).

Findgames8.png

ServerRow 위젯에 대한 OnClicked 이벤트는, 게임 인스턴스를 구한 다음 Cast To MyGameInstance 노드를 사용하여 그 안에서 Join from Server List Event 를 호출합니다. RefreshListMacro 과정에서 생성된 SearchResult 변수도 MyGameInstance 블루프린트에 전달하여 플레이어가 클릭한 서버에 참가 시도할 수 있도록 합니다.

MyGameInstance 블루프린트 안의 JoinFromServerListEvent 는 (아래 그림), 호출되면 먼저 ShowLoadingScreen 커스텀 이벤트를 호출합니다 (게임 호스팅 섹션에 소개되어 있습니다).

Findgames9.png

로딩 화면이 표시되는 동안, 플레이어가 참가를 위해 클릭한 ServerRow 위젯 블루프린트에서 제공된 Search ResultJoin Session 노드를 사용하여 참가 시도합니다. 성공하면 플레이어는 선택된 서버에 참가하여 그 게임에 스폰됩니다. 오류가 있는 경우, DisplayErrorDialog 매크로 를 실행하여 Failed to join session 라는 Error Message 가 표시됩니다.

게임플레이

플레이어가 게임플레이 도중 캐릭터를 취하기 전에, 캐릭터와 게임 상태 셋업이 이루어져야 합니다 (또는 게임에 참가하는 경우, 게임을 업데이트하여 새로운 플레이어가 참가하였음을 알려야 합니다). 메인 메뉴에서 Play 버튼을 클릭하거나 서버 리스트 메뉴에서 참가할 서버를 선택하는 경우, 가장 먼저 일어나는 일은 Game Mode 블루프린트 안에서 Post Login 이벤트로 아래와 같은 셋업 프로세스가 시작됩니다.

Gameplay1.png

Event Post Login 이 발동되면, 먼저 Switch Has Authority (1) 라는 엔진 매크로를 실행, 현재 실행중인 스크립트가 네트워크 오소리티(서버)에서 실행되었는지 아니면 원격 머신(클라이언트)에서 실행되었는지 검사합니다. 이 프로세스는 게임을 호스팅하든 참가하든 서버에서 일어나기 때문에, Remote 핀은 아무데도 가지 않지만, Authority 핀은 계속해서 Post Login 스크립트를 이어갑니다.

Switch Has Authority 에 대한 또다른 예제는, 1.2 - 블루프린트로 네트워크 오소리티 및 원격 클라이언트 감지 페이지를 참고하세요.

(2) 에서, New Player 의 PlayerStateMyPlayerState 블루프린트로 형변환되며, 거기서 Player Number 를 설정(3) 및 사용하여 표시된 Scoreboard 의 플레이어 순서가 모든 플레이어에 대해 같도록 합니다 (새로 추가되는 각 플레이어마다, Scoreboard 리스트에도 추가됩니다). Player Number 설정 이후, New Player 역시 MyPlayerController 블루프린트로 형변환하여 ClientPostLogin 커스텀 이벤트가 발동되도록 합니다.

Gameplay2.png

위에서, ClientPostLogin 이벤트의 디테일 패널을 통해 약간의 프로퍼티가 할당되었습니다.

Gameplay3.png

그래프 섹션 아래, Replicates 옵션을 Run on owning Client 로 설정하고 Reliable 체크박스를 체크했습니다. 이 두 가지 옵션을 사용하여 이 이벤트 이후의 스크립트가 서버에서 호출되지만 소유중인 클라이언트 머신에서만 실행되도록 하는 것입니다. Reliable 세팅은 이 스크립트가 열악한 네트워크 상태로 인해 분실되지 않고 반드시 실행되도록 보장해 줍니다 (장식성 비주얼을 처리하는 대부분의 리플리케이티드 함수는 네트워크 대역폭 감소를 위해 Unreliable 이지만, 이 경우 반드시 일어나도록 해야 하므로 Reliable 로 설정합니다).

이제 스크립트 어디에 발생해야 할지를 알았으니, Setup Ingame UI 함수를 호출합니다.

Gameplay4.png

이 함수는 Branch (1) 로 시작하여 타깃으로 삼은 컨트롤러가 로컬 플레이어 타깃인지 검사한 다음, 그렇다면 Create Widget (2) 을 사용하여 HUD 위젯 블루프린트를 생성합니다. 그 후 HUD 위젯을 HUD Widget (3) 으로 승격시키고 Add to Viewport (4) 노드로 위젯을 플레이어의 뷰포트에 추가시킵니다. (5) 에서 또다른 Create Widget 노드를 사용하여 InGame Menu 위젯 블루프린트를 생성하고 InGameMenuWidget 변수로 승격(6)시켜, 플레이어가 메뉴를 띄우기 위한 버튼을 누르면 In Game Menu 를 표시하기 위해 호출할 수 있습니다.

이 시점에서, "login" 프로세스가 완료되어 캐릭터 자체의 셋업이 Character Animation Blueprint 를 통해 일어납니다. 각각의 캐릭터 이동 상태를 정의하고 애니메이션을 설정하였으나, 그 부분은 여기서 다루지 않겠습니다. 애니메이션 블루프린트 관련 상세 내용은 애니메이션 블루프린트 문서를 참고하세요.

Character Animation Blueprint 구성이 완료된 이후, Level_01 맵이 열립니다. 이 맵의 레벨 블루프린트 에서, 플레이어가 실제 레벨에 스폰되기 전 다음 스크립트가 호출됩니다.

level1LevelBlueprint.png

위에서 이 맵의 Event Begin Play (플레이 시작)시, 현재 게임 인스턴스에 대해 Cast To MyGameInstance 노드가 호출되며, 거기서 Start Playing State 함수가 호출됩니다. MyGameInstance 블루프린트 안의 이 함수는 아래와 같이 게임 스테이트를 Playing 으로 변경합니다.

playingState.png

스테이트가 Playing 으로 변경된 이후, 마우스 커서는 Set Focus to Game Viewport 노드로 (이전 그림의 3) 게임 뷰포트에 고정되며, UI 입력은 Set Input Mode Game Only 노드를 (이전 그림의 4) 사용하여 무시합니다.

게임에서 접속 끊기

게임에서 접속을 끊는 프로세스는 꽤나 간단하여, 일부 UMG 위젯 표시를 켜고/끄는 작업과, 처음 게임을 로드할 때 메인 메뉴로 돌아가는 동일한 시작 프로세스를 활성화시키는 작업이 포함됩니다.

게임플레이 도중 Q 가 눌려 게임내 일시정지 메뉴가 표시되고, Leave Game 옵션을 클릭하자마자 InGameMenu 위젯 블루프린트 안에서 다음과 같은 프로세스가 발생합니다:

disconnectingGraph.png

위에서, Leave Button 자체를 클릭하면 (1) 이벤트가 발동되어 소유중인 플레이어를 구하는 것으로 MyPlayerController 블루프린트로 Cast To 됩니다. MyPlayerController 블루프린트 안에서 Hide in Game Menu (3) 가 호출되는데, 아래와 같습니다.

hideingamemenu.png

이 스크립트 부분은 (앞서 만들어 레퍼런스로 저장한) In Game Menu Widget 변수를 구한 다음, Remove from Parent 노드로 화면에서 제거합니다. 그 후 Set Input Mode Game Only 를 사용하여 UI 입력이 가능하도록 입력 모드를 다시 변경할 때까지 플레이어의 다른 UI 관련 입력 동작을 막도록 합니다.

그런 다음 스크립트는 InGameMenu 위젯 블루프린트와 Cast to MyGameInstance 노드(4)로 돌아와 현재 게임 인스턴스를 구하고 그 안에서 Show Main Menu Event 함수를 호출하는데, 거기서 함수가 처음 하는 일은 IsCurrentState 매크로 와 게임 첫 로드시 Startup 섹션에서 그 뒤에 따르는 섹션을 실행하는 것입니다.

disconnectingGraph.png