GameMode & GameState
게임 규칙, 상태 관리, 플레이어 관리의 프레임워크를 이해합니다
게임 프레임워크 클래스
GameMode, GameState, PlayerState, PlayerController의 역할
// UE5 게임 프레임워크 핵심 클래스
AGameModeBase // 서버에만 존재. 게임 규칙의 심판
├─ 기본 클래스 지정 (Pawn, PlayerController, GameState, HUD)
├─ 플레이어 로그인/로그아웃 처리
├─ 매치 시작/종료 관리
└─ 스폰 규칙 정의
AGameStateBase // 모든 클라이언트에 복제. 게임 공유 상태
├─ 매치 시간, 점수
├─ 팀 정보
└─ 모든 PlayerState 배열 보유
APlayerState // 개별 플레이어 정보 (복제됨)
├─ 플레이어 이름
├─ 점수
└─ Pawn이 교체되어도 유지
APlayerController // 플레이어의 입력과 카메라 관리
├─ 입력 처리
├─ HUD/위젯 관리
└─ Pawn Possess/UnPossess
| 클래스 | 존재 위치 | 수명 | 주 용도 |
|---|---|---|---|
| GameMode | 서버만 | 레벨 수명 | 규칙, 스폰, 매치 관리 |
| GameState | 서버+클라이언트 | 레벨 수명 | 공유 상태 (점수, 시간) |
| PlayerState | 서버+클라이언트 | 플레이어 접속 중 | 개인 상태 (이름, 점수) |
| PlayerController | 소유자 클라이언트+서버 | 플레이어 접속 중 | 입력, UI, Pawn 제어 |
GameMode 설정과 활용
게임 규칙의 정의와 기본 클래스 지정
GameMode에서 기본 클래스 지정
// BP_GameMode > Class Defaults
Classes
├─ Default Pawn Class: BP_PlayerCharacter
├─ Player Controller Class: BP_PlayerController
├─ Game State Class: BP_GameState
├─ Player State Class: BP_PlayerState
└─ HUD Class: BP_HUD
// 프로젝트 전체 기본: Project Settings > Maps & Modes
// 레벨별 설정: World Settings > Game Mode Override
GameMode 주요 오버라이드 함수
// 플레이어 리스폰 로직
[Override: HandleStartingNewPlayer]
└──> [Parent Call] ──> [Find Player Start] ──> [Spawn Default Pawn]
// 게임 시작 조건
[Override: ReadyToStartMatch]
└──> [Branch: NumPlayers >= MinPlayers]
├─ True ──> Return True (매치 시작)
└─ False ──> Return False (대기)
// 유용한 GameMode 노드
Get Game Mode // 현재 GameMode 참조 (서버에서만 유효)
RestartPlayer // 플레이어 리스폰
FindPlayerStart // PlayerStart 위치 찾기
HasMatchStarted // 매치 시작 여부
멀티플레이어에서 GameMode는 서버에만 존재합니다. 클라이언트에서 Get Game Mode를 호출하면 null을 반환합니다. 모든 플레이어가 접근해야 하는 데이터는 GameState에 저장하세요.
GameState와 PlayerState
게임 공유 상태와 플레이어별 상태 관리
GameState 활용
// BP_GameState 변수
Variables:
├─ MatchTimeRemaining: Float (Replicated)
├─ TeamAScore: Integer (Replicated)
├─ TeamBScore: Integer (Replicated)
└─ CurrentWave: Integer (Replicated)
Event Dispatchers:
├─ OnScoreUpdated (TeamIndex: Integer, NewScore: Integer)
└─ OnMatchStateChanged (NewState: Name)
// 접근 방법:
[Get Game State] ──> [Cast to BP_GameState]
// 또는
[Get Game State] ──> Interface Call (하드 참조 방지)
PlayerState 활용
// BP_PlayerState 변수
Variables:
├─ KillCount: Integer (Replicated)
├─ DeathCount: Integer (Replicated)
├─ SelectedCharacterClass: E_CharacterClass (Replicated)
└─ TeamID: Integer (Replicated)
// Pawn에서 PlayerState 접근:
[Get Player State] ──> [Cast to BP_PlayerState]
// 모든 PlayerState 순회:
[Get Game State] ──> [Get Player Array] ──> [ForEachLoop]
PlayerState: 다른 플레이어도 볼 수 있어야 하는 정보 (점수, 이름, 팀) → 복제됨
PlayerController: 해당 플레이어만 아는 정보 (설정, UI 상태) → 복제 안 됨
싱글플레이어 게임에서는 구분이 덜 중요하지만, 나중에 멀티플레이를 고려한다면 처음부터 올바르게 분리하는 것이 좋습니다.
실전 GameMode 패턴
웨이브 게임과 라운드 기반 게임의 GameMode 구현
// BP_WaveGameMode - 웨이브 생존 게임
Variables:
├─ CurrentWave: Integer = 0
├─ EnemiesRemaining: Integer = 0
├─ WaveEnemyCounts: Array<Integer> = [5, 8, 12, 15, 20]
└─ SpawnPoints: Array<Actor>
Functions:
├─ StartNextWave()
│ ├─ CurrentWave++
│ ├─ EnemiesRemaining = WaveEnemyCounts[CurrentWave]
│ ├─ Timer: SpawnOneEnemy (1.5s, Looping)
│ └─ GameState.OnWaveStarted.Call(CurrentWave)
│
├─ OnEnemyKilled(Enemy: Actor)
│ ├─ EnemiesRemaining--
│ ├─ GameState.UpdateScore()
│ └─ Branch: EnemiesRemaining <= 0
│ └─ True: Delay(3.0) → StartNextWave()
│
└─ OnPlayerDeath(Player: Controller)
├─ Branch: AnyPlayersAlive?
│ ├─ True: Delay(5.0) → RestartPlayer(Player)
│ └─ False: EndMatch("Defeat")
└─ GameState.OnPlayerDied.Call()
AGameModeBase: 기본 기능만 제공. 싱글플레이어나 단순한 멀티플레이어에 적합.
AGameMode (AGameModeBase 상속): 매치 상태 머신(Match State), 준비 완료(Ready) 시스템 등 멀티플레이어 추가 기능 포함. 복잡한 멀티플레이어 게임에 적합.
싱글플레이어 게임이라면 GameModeBase로 충분합니다.
핵심 요약
- GameMode는 서버에만 존재하며, 게임 규칙과 기본 클래스(Pawn, Controller, State)를 지정한다
- GameState는 모든 플레이어에게 복제되어 공유 상태(점수, 시간)를 관리한다
- PlayerState는 개별 플레이어 정보를 저장하며, Pawn이 교체되어도 유지된다
- PlayerController는 입력 처리와 UI 관리를 담당한다
- 클라이언트에서
Get Game Mode는 null을 반환하므로, 공유 데이터는 GameState에 저장한다 - 싱글플레이어는 GameModeBase, 복잡한 멀티플레이어는 GameMode를 사용한다
도전 과제
배운 내용을 직접 실습해보세요
BP_GameMode를 생성하고 DefaultPawnClass, PlayerControllerClass, HUDClass를 커스텀 BP로 지정하세요. World Settings에서 GameMode Override를 설정하고, InitGame/StartPlay 이벤트에 로그를 추가하여 초기화 순서를 확인하세요.
BP_GameState에 CurrentRound(Integer), RoundTimeRemaining(Float), TeamScores(Integer Array) 변수를 추가하세요. GameMode에서 라운드 시작/종료 로직을 구현하고, GameState를 통해 모든 클라이언트에서 조회 가능하게 하세요.
완전한 게임 프레임워크를 구현하세요: GameMode가 플레이어 스폰을 관리하고, GameState가 점수와 라운드를 추적하며, PlayerState가 개인 킬/데스 통계를 저장합니다. Get All Players Of Class로 전체 플레이어 목록을 조회하는 스코어보드도 구현하세요.