Gameplay Framework

김혁·2025년 8월 5일

챌린지

목록 보기
2/14

언리얼 Framework 4대 클래스

  1. GameMode : 게임의 심판관
  2. GameState : 게임의 상황판
  3. PlayerState : 개인 데이터
  4. GameInstance : 게임의 관리자

GameMode

  • 게임 규칙(게임 승리 조건, 플레이어 시작 위치, Default Pawn Class 등)을 정의하는 클래스
  • 한 레벨당 하나만 존재
  • 서버에서만 동작함

GameModeBase vs GameMode

GameModeBase

  • 경량화된 게임 모드 클래스로 가장 기본적인 게임 진행 관리 기능만 제공
  • 게임 시작/종료, 플레이어 스폰 등 최소 기능만 제공
  • 캐주얼 게임, 퍼즐 게임, RPG 등 매치 로직이 명확하지 않거나 단순한 게임에서 활용

GameMode

  • GameModeBase를 상속한 확장형 클래스로 다양한 기능을 제공
  • 클래식한 FPS/TPS 규칙(팀전, 스코어, 시간, 승리 조건 등) 지원
  • 자동 리스폰 시스템, 관전자 모드, 팀 기반 매치 등 더 많은 기능을 기본적으로 제공
  • 경쟁 기반 게임(FPS, 배틀로얄 등)에서 활용

조합 규칙

  • GameModeBase <-> GameStateBase
  • GameMode <-> GameState
  • 교차해서 사용할 시에는 에러 발생하기 때문에 상황에 맞게 조합을 맞춰서 사용해야 함

GameState

  • 현재 게임의 상태(점수/시간, 팀 정보, 게임 진행 상황 등)를 전체적으로 공유하는 클래스
  • 클라이언트와 서버 모두 존재
  • GameMode의 상태를 복제해서 모든 플레이어가 알 수 있도록 함

핵심 철학

  • 정보 제공자 : 게임 모드에서 관리하면서 보여줄 정보만을 표시
  • 읽기 전용 : UI에서 참조만! 직접 수정은 불가!
  • GameMode 전용 업데이트 : 다른 곳에서 수정하면 안 됨!

-> 읽기 전용으로 가지고 있는 게임 상태 모음
-> 게임모드에서 해주는 업데이트된 정보를 가지고 있고, 가지고 있는 데이터를 필요한 포맷에 맞게 UI 등에 반환해주는 전광판

PlayerState

  • 각 플레이어의 개별 정보(점수, 킬/데스, 유저 이름 등)를 저장하는 클래스
  • 클라이언트와 서버 모두 존재
  • 죽어도 사라지지 않음(정보 유지)
  • 네트워크 멀티플레이에서 핵심적인 클래스

생명 주기 특징

  • GameMode, GameState : 레벨 전환 시에 파괴되었다가 새로 생성됨
  • PlayerState : 레벨 전환 시에 유지됨.
    -> 플레이어의 점수, 이름, 팀 정보 등 게임 중 지속되어야 할 상태 정보를 저장하는 클래스이기 때문.

소유권 구조 및 올바른 접근 방법

GameMode -> PlayerController -> PlayerState
	↓				↓				 ↓
  권한자			  소유자			 실제 데이터
  • PlayerController가 PlayerState를 가지고 있는데, GameMode가 PlayerController를 가지고 있다. 이 구조라면 레벨 전환 시에는 어떻게 될까?
    -> GameMode, PlayerController가 레벨 전환 시 파괴되고 새로 생성되면, PlayerState는 파괴되지 않고 유지되어, GameMode가 PostLogin 시점에 PlayerController를 기존의 PlayerState와 다시 연결한다.
// 잘못된 접근 - 직접 게임 스테이트에서 플레이어 배열에 접근하는 방식
AMyPlayerState* PS = GetWorld()->GetGameState()->PlayerArray[0];

// 올바른 접근 - 플레이어 컨트롤러를 통해 접근
AMyPlayerState* PS = GetPlayerState<AMyPlayerState>();

GameInstance

  • 게임 전체(세션 정보, 플레이어 정보)를 아우르는 전역 객체
  • 레벨이 바뀌어도 유지됨
  • 게임 시작 ~ 종료까지 살아있음.

절대적인 특징

  • 게임 전체 생명주기 : 게임 시작부터 게임 종료까지 살아있음
  • 레벨 간 데이터 유지 : 레벨 바뀌어도 파괴되지 않고 유지됨
  • 레벨 전환 권환 : 오직 GameInstance만 레벨 바꿀 수 있음

Framework 로딩 순서

- 엔진 부팅 단계
1. 엔진 초기화 (UEngine 생성)
2. GameInstance::Init()

- 첫 레벨 로딩 단계
3. World 생성
4. GameMode 생성
5. GameState 생성
6. PlayerController 생성
7. PlayerState 생성
8. Pawn 생성

9. 이후 모든 BeginPlay() 호출 -> 순서 보장 안됨

- 레벨 전환 시
10. 모든 액터의 EndPlay() 호출
11. 기존 World 파괴(GameMode, GameState 사라짐)
12. PlayerState는 새 World로 이주
13. 3~9번 과정 반복 -> 7번 과정에서 PlayerController와 기존 PlayerState 재연결

각 단계에서 할 수 있는 것/없는 것

GameInstance::Init()

  • 할 수 있는 것
    • 글로벌 설정 로드
    • 서브시스템 초기화
    • SaveGame 데이터 로드
  • 할 수 없는 것
    • GetWorld() 호출
    • GameMode, PlayerController 접근
    • UI 생성

GameMode 생성자

  • 할 수 있는 것
    • 기본 클래스 설정
    • 게임 규칙 변수 초기화
  • 할 수 없는 것
    • GameState 접근
    • PlayerController 접근

PostInitializeComponents()

  • 할 수 있는 것
    • GameState 접근
    • 다른 Framework 객체들과 통신

언리얼 설계 사고법

데이터 위치 결정

  1. 생명주기 : 언제까지 살아있어야 하는가?
  • 레벨 끝까지 : GameMode/GameState
  • 게임 끝까지 : PlayerState/GameInstance
  1. 수정 권한 : 누가 바꿀 수 있는가?
  • 게임 시스템 : GameMode가 관리
  • 플레이어 개인 : PlayerState가 관리
  1. 참조 대상 : 누가 봐야 하는가
  • UI 표시 : GameState/PlayerState
  • 내부 로직 : private 멤버


출처: 팀스파르타 내일배움캠프
profile
게임 개발자를 향해..

0개의 댓글