게임 모드와 게임 스테이트

Game Mode, 게임 모드와 Game State, 게임 스테이트에 대한 개요입니다.

Windows
MacOS
Linux

플레이중인 게임의 정보를 처리하는 클래스는 크게 Game Mode (게임 모드)와 Game State (게임 스테이트), 둘입니다.

가장 제약이 없다는 게임일지라도 토대가 되는 규칙들이 있으며, 이러한 규칙들이 게임 모드를 이룹니다. 가장 기본적인 수준에서 이러한 규칙에 포함되는 것은 다음과 같습니다:

  • 존재하는 플레이어와 관람자의 수는 물론, 허용된 플레이어와 관람자 최대 수

  • 플레이어가 게임에 들어오는 방식, 스폰 위치 선택 규칙과 기타 스폰/리스폰 동작 포함 가능

  • 게임 일시정지 가능 여부, 게임 일시정지 처리 방식

  • 레벨간의 전환, 게임의 시네마틱 모드 시작 여부 포함

게임에 규칙 관련 이벤트가 발생하고 트래킹을 통해 모든 플레이어와 공유할 필요가 있을 때, 그 정보는 게임 스테이트 에 보관되고 그를 통해 동기화됩니다. 이 정보에 포함되는 것들은 다음과 같습니다:

  • 게임 실행 기간 (로컬 플레이어 참가 전 실행 시간 포함).

  • 각 플레이어의 게임 참가 기간, 그 플레이어의 현재 상태.

  • 현재 게임 모드의 베이스 클래스.

  • 게임 시작 여부.

게임 모드

플레이하는 데 필요한 플레이어 수, 그 플레이어가 게임에 참가하는 방식 등의 기본적인 요소들은 여러 유형의 게임에 공통이지만, 어떤 게임을 개발하는지에 따라 무한대의 규칙 변종이 가능합니다. 그 규칙과이 무엇이든, 그 정의와 구현은 게임 모드에 합니다. 현재 게임 모드에 흔히 쓰이는 베이스 클래스는 둘 입니다.

엔진 버전 4.14 에는 AGameModeBase 가 도입되었는데, 모든 게임 모드의 베이스 클래스로, 고전 AGameMode 를 단순화시키고 효율화시킨 버전입니다. 4.14 이전의 게임 모드 베이스 클래스였던 AGameMode 는 전과 마찬가지로 존재하며 기능도 그대로이지만, 이제 AGameModeBase 의 자손이 되었습니다. AGameMode 는 그 경기 상태 개념 구현 방식상 멀티플레이어 슈팅과 같은 표준 게임 유형에 보다 적합합니다. AGameModeBase 는 새로운 코드 프로젝트에 포함된 새로운 기본 게임 모드로, 보다 단순하고 효율적입니다.

AGameModeBase

모든 게임 모드는 AGameModeBase 의 서브클래스로, 덮어쓸 수 있는 기본 함수 기능이 상당량 들어있습니다. 흔히 쓰이는 함수는 다음과 같습니다:

함수/이벤트

용도

InitGame

InitGame 이벤트는 (PreInitializeComponents 를 포함한) 다른 스크립트 전에 호출되어, 파라미터를 초기화시키고 그 헬퍼 클래스를 스폰시킵니다.

이 함수는 다른 액터가 Game Mode 인스턴스 자체를 포함해서 PreInitializeComponents 를 호출하기 전에 호출됩니다.

PreLogin

서버에 접근 시도중인 플레이어를 수락 또는 거부합니다. ErrorMessage 에 공백이 아닌 스트링을 입력하면 Login 함수가 실패하도록 만듭니다. PreLoginLogin 전 호출되며, 참가하는 플레이어가 게임 콘텐츠를 다운로드해야 하는 경우 시간이 한참 지나서야 Login 이 호출될 수도 있습니다.

PostLogin

로그인 성공 이후 호출됩니다. PlayerController 에서 리플리케이트되는 함수 호출을 하기에 안전한 첫 번째 장소입니다. 블루프린트로 OnPostLogin 을 구현하여 부가 로직을 추가할 수 있습니다.

HandleStartingNewPlayer

PostLogin 또는 심리스 트래블 이후 호출되며, 블루프린트에서 덮어써서 새 플레이어에게 벌어지는 일을 변경할 수 있습니다. 기본적으로 플레이어에 대한 폰을 생성합니다.

RestartPlayer

플레이어의 폰 스폰을 시작하기 위해 호출됩니다. 폰의 스폰 위치를 지정하고자 하는 경우 사용할 수 있는 함수 RestartPlayerAtPlayerStartRestartPlayerAtTransform 도 있습니다. OnRestartPlayer 를 블루프린트에서 구현하여 이 함수 완료 후의 로직을 추가할 수 있습니다.

SpawnDefaultPawnAtTransform

플레이어의 폰이 실제 스폰되는 곳으로, 블루프린트에서 덮어쓸 수 있습니다.

Logout

플레이어가 게임을 떠나거나 소멸되었을 때 호출됩니다. OnLogout 을 구현하여 블루프린트 로직을 짤 수 있습니다.

게임이 제공하는 경기 포맷, 미션 유형, 특별 지역 각각에 대해 AGameModeBase 클래스의 서브클래스를 만들 수 있습니다. 게임에는 게임 모드가 몇이든 있을 수 있듯이 AGameModeBase 의 서브클래스도 그러하지만, 한 번에 하나의 게임 모드만 사용할 수 있습니다. 게임 모드 액터는 UGameEngine::LoadMap() 를 통해 플레이할 레벨을 초기화시킬 때마다 인스턴스를 만듭니다.

게임 모드는 멀티플레이어 게임에 참가하는 원격 클라이언트에 리플리케이트되지 않습니다. 서버에만 존재하므로, 로컬 클라이언트는 원본 게임 모드 클래스 (또는 블루프린트)를 볼 수 있지만 실제 인스턴스에 접근하여 변수를 확인하고 게임 도중 무엇이 변경되었는가 확인할 수는 없습니다. 플레이어가 현재 게임 모드 관련해서 업데이트된 정보가 필요한 경우, 그 정보는 AGameStateBase 액터에 저장된 내용을 통해 쉽게 동기화 상태를 유지할 수 있으며, 이 중 하나를 게임 모드와 함께 생성한 다음 모든 원격 클라이언트로 리플리케이트합니다.

AGameMode

AGameModeAGameModeBase 의 서브클래스로, 멀티플레이어 경기 및 기존 작동방식 지원을 위한 부가 함수가 몇 가지 들어있습니다. 새롭게 생성되는 프로젝트는 모두 AGameModeBase 를 기본 사용하지만, 그 부가 함수가 필요한 경우 AGameMode 를 상속하도록 전환할 수 있습니다. AGameMode 를 상속하는 경우, 경기 스테이트 머신도 지원하는 AGameState 에서 게임 스테이트를 상속하기도 해야합니다.

AGameMode 에는 경기 또는 일반 게임플레이 흐름 상태를 기록하는 스테이트 머신이 들어있습니다. 현재 상태를 질의하기 위해서는 GetMatchState 또는 HasMatchStarted, IsMatchInProgress, HasMatchEnded 와 같은 래퍼(wrapper)를 사용하면 됩니다. 가능한 경기 상태는 다음과 같습니다:

  • EnteringMap (맵 진입)은 초기 상태입니다. 액터 틱은 아직 이루어지지 않고 있으며, 월드는 제대로 초기화되지 않은 상태입니다. 모두 완전히 로드되면 다음 상태로 전환될 것입니다.

  • WaitingToStart (시작 대기중)가 그 다음 상태로, 여기에 들어갈 때 HandleMatchIsWaitingToStart (경기 시작 대기중 처리)가 호출됩니다. 액터 틱은 이루어지지만, 플레이어는 아직 스폰되어있지 않습니다. ReadyToStartMatch (경기 시작 준비)가 true 를 반환하는 경우, 또는 StartMatch 가 호출된 경우 다음 상태로 전환됩니다.

  • InProgress (진행중)은 게임의 주요 부분이 일어나는 상태입니다. 여기에 들어갈 때 HandleMatchHasStarted (경기 시작 처리)가 호출되며, 그 후 모든 액터에서 BeginPlay (플레이 시작)을 호출합니다. 이 시점에서 일반적인 게임플레이가 진행됩니다. ReadyToEndMatch (경기 종료 준비)가 true 를 반환하거나 EndMatch (경기 종료)가 호출되는 경우 경기가 다음 상태로 전환됩니다.

  • WaitingPostMatch (경기 후 대기)는 끝에서 두 번째 상태로, 여기에 들어설 때 HandleMatchHasEnded (경기 종료 처리)가 호출됩니다. 액터 틱은 여전히 일어나지만 새로운 플레이어는 참가할 수 없습니다. 맵 이동이 시작되면 다음 상태로 전환됩니다.

  • LeavingMap (맵 떠나기)는 일반적인 흐름의 마지막 상태로, 여기에 들어설 때 HandleLeavingMap (맵 떠나기 처리)를 호출합니다. 경기가 이 상태에 머물러있다가 맵 전환이 일어나면 EnteringMap (맵 진입) 상태로 돌아갑니다.

  • Aborted (중단된)은 실패 상태로, AbortMatch (경기 중단)을 호출하면 시작됩니다. 복구할 수 없는 오류가 발생했을 때 설정됩니다.

경기 상태는 거의 항상 InProgress (진행중) 상태에 머물러있게 되는데, BeginPlay (플레이 시작)이 호출되고 액터 틱이 시작되는 곳이기 때문입니다. 하지만 다른 게임에서 보다 복잡한 규칙의 멀티플레이어 게임을 만드는 경우, 예를 들어 멀티플레이어 슈팅 게임에서 다른 플레이어 참가를 기다리는 동안 플레이어가 레벨을 자유롭게 날아다닐 수 있게 하려는 경우, 위와 같은 상태를 덮어쓰면 됩니다.

게임 모드 블루프린트

게임 모드 클래스에서 파생된 블루프린트를 만들고, 그것을 프로젝트나 레벨의 기본 게임 모드로 사용하는 것이 가능합니다.

게임 모드에서 파생된 블루프린트는 다음과 같은 기본값 설정이 가능합니다:

추가로 게임 모드 블루프린트는 코드를 변경하지 않고도 변수를 조절할 수 있어서 매우 유용합니다. 그러면 하드코딩된 애셋 레퍼런스를 사용하거나 조정이 필요할 때마다 기술적인 지원 및 코드 변경 필요 없이 각기 다른 다수의 레벨에 하나의 게임 모드를 적용시킬 수 있는 것입니다.

게임 모드 설정

레벨의 GameMode 설정을 위한 메서드는 여러가지 있습니다. 여기서는 우선권이 가장 낮은 것에서부터 높은 것으로 나열해 보겠습니다:

  • DefaultEngine.ini 파일의 /Script/EngineSettings.GameMapsSettings 섹션에 GlobalDefaultGameMode 항목으로 설정해 주면 프로젝트의 모든 맵에 대한 기본 게임 모드를 설정합니다.

    [/Script/EngineSettings.GameMapsSettings]
    GlobalDefaultGameMode="/Script/MyGame.MyGameGameMode"
    GlobalDefaultServerGameMode="/Script/MyGame.MyGameGameMode"
  • 개별 맵에 대해 프로젝트 세팅을 덮어쓰려면, 에디터에서 World SettingsDefault Game Mode 를 설정합니다.

    WorldSettings_GameMode.png

  • URL 을 실행파일에 붙여 게임 시작시 로드할 맵을 강제 지정할 수 있습니다. game 옵션을 사용하여 게임 모드를 설정할 수 있습니다. 자세한 정보는 명령줄 인수 문서를 참고하시기 바랍니다.

    UE4Editor.exe /Game/Maps/MyMap?game=MyGameMode -game
  • 마지막으로 DefaultEngine.ini 파일의 /Script/Engine.WorldSettings/ 섹션에 맵 접두사(와 URL 메서드에 대한 앨리어스)를 설정할 수 있습니다. 이 접두사는 접두사가 붙은 모든 맵에 대한 기본 게임 모드를 설정합니다.

    [/Script/EngineSettings.GameMapsSettings]
    +GameModeMapPrefixes=(Name="DM",GameMode="/Script/UnrealTournament.UTDMGameMode")
    +GameModeClassAliases=(Name="DM",GameMode="/Script/UnrealTournament.UTDMGameMode")

Game Mode 셋업 예제는 게임 모드 구성 문서를 참고하세요.

게임 스테이트

Game State (게임 스테이트)는 클라이언트가 게임의 상태를 모니터링할 수 있도록 해줍니다. 개념적으로 게임 스테이트는 접속된 모든 클라이언트가 알아야 하는 정보, 플레이어 개개인이 아닌 게임 모드에 관련된 정보를 관리해야 합니다. 그래서 접속된 플레이어 목록, 깃발뺏기 게임의 팀 점수, 오픈 월드 게임에서 완료한 미션 등과 같은 게임 전반적인 프로퍼티 기록을 유지할 수 있습니다.

게임 스테이트는 깃발 뺏기 게임에서 특정 플레이어가 팀 점수를 몇 점이나 올렸는가와 같은 개별 플레이어 단위의 기록을 유지하기에 좋은 곳은 아닙니다. 그런 부분은 Player State (플레이어 스테이트)에서 보다 깔끔하게 처리할 수 있기 때문입니다. 일반적으로 게임 스테이트는 게임플레이 도중 변하면서 모두에게 관련이 있고 보일 수 있는 프로퍼티 기록을 유지해야 합니다. 게임 모드는 서버에만 존재하는 반면, 게임 스테이트는 서버에 존재하면서 모든 클라이언트에 리플리케이트되어, 연결된 모든 기기의 게임 최신 상태를 유지합니다.

AGameStateBase 는 기본 구현이며, 그 중 몇 가지 기본 함수 기능은 다음과 같습니다:

함수 또는 변수

용도

GetServerWorldTimeSeconds

UWorld 함수 GetTimeSeconds 의 서버 버전으로, 클라이언트와 서버 양쪽에서 동기화되어 리플리케이션에 믿고 사용할 수 있는 시간으로 활용합니다.

PlayerArray

모든 APlayerState 오브젝트의 배열로, 게임의 모든 플레이어에게 어떤 작업을 할 때 유용합니다.

HasBegunPlay

게임의 액터에 대해 BeginPlay 함수가 호출된 경우 true 를 반환합니다.

AGameStateBase 는 게임에서 무슨 일이 벌어지고 있는지 플레이어에게 지속적으로 알리기 위해 필요한 변수와 함수를 넣기 위해 C++ 또는 블루프린트로 자주 확장시키는 클래스입니다. 게임 스테이트를 만들 때 대상으로 짝지어진 게임 모드를 기반으로 구체적인 변경사항이 이루어집니다. 게임 모드 자체에서도 그 기본 게임 스테이트 유형을 AGameStateBase 에서 파생된 C++ 클래스 또는 블루프린트로 덮어쓸 수 있습니다.

Select Skin
Light
Dark

새로운 언리얼 엔진 4 문서 사이트에 오신 것을 환영합니다!

문서 사이트에 대한 의견을 모을 수 있는 피드백 시스템을 포함해서 여러가지 새로운 기능을 준비하고 있습니다. 아래 Documentation Feedback 포럼(영문) 또는 언리얼 엔진 네이버 공식 카페(한글) 중 편하신 곳에 의견이나 문제점을 알려 주세요.

새 시스템이 준비되면 알려 드리겠습니다.

네이버 카페
공식 포럼