언리얼엔진5 공부

GameState

Client Side 2025. 10. 17. 21:31

게임 스테이트를 사용하는 이유

 

1. 중앙 집중관리 (Centralized Management)

 

  • 캐릭터에 저장하면 : 만약 플레이어가 여러 명이라면? 아니면 플레이어가 죽었다가 다시 살아나면? 점수가 리셋되거나 다른 플레이어의 점수를 가져올 수 없게 된다. 점수는 플레이어 개개인의 상태보다는 게임 전체의 상태에 가깝다.
  • CoinItem에 저장하면 : 코인 아이템은 점수를 가지고 있을 뿐이고, 총 점수를 저장하는 용도가 아니다. 아이템이 사라지면 점수도 사라진다.
  • GameState에 저장하면 : GameState는 게임의 전반적인, 임시적인 상태(스코어, 게임 시간, 게임 진행 상황 등)를 관리하는 데 특화된 객체. 즉, 지금 이 레벨의 총 점수를 저장하기에 가장 적합한 곳이다. 어떤 액터든 World->GetGameState()를 통해 현재 점수에 쉽게 접근하고 수정할 수 있다.

 

2. 멀티 플레이 환경에서의 복제

  • 언리얼 엔진의 GameState는 기본적으로 네트워크 복제를 고려해서 설계되었다. 만약 멀티플레이어 게임이라면, 서버에서 GameState의 점수를 변경하면 자동으로 모든 클라이언트에 그 변경 사항이 동기화된다.
  • 다른 액터에 점수를 저장하면, 이 점수를 모든 클라이언트에게 정확하고 안정적으로 보여주기가 훨씬 복잡해진다. GameState를 사용하면 언리얼 엔진이 알아서 처리해 주는 부분이 많다.

 

3. 코드의 구조화 및 의도 명확화

  • 언리얼 엔진은 GameMode, GameState, PlayerController, PlayerState, Character 등 각각의 역할에 맞는 핵심 클래스들이 존재한다
    • GameMode: 게임의 규칙 (누가 이기고 지는지, 스폰 위치 등)
    • GameState: 게임의 상태 (현재 점수, 남은 시간 등)
    • PlayerController: 플레이어의 입력, 카메라 제어 등
    • PlayerState: 개별 플레이어의 상태 (이름, 개인 점수, KDA 등)
    • Character: 물리적인 캐릭터, 이동, 액션

 

GameState를 사용할 때

  • GameState를 단순 참조하여 사용할 때
    • #include "PracticeGameState.h” 만 헤더에 추가시켜주면 된다. 이건 이런 클래스가 있다고 컴파일러에게 알려주는 정도이다.
    • 전방선언은 클래스의 존재만 알려주는 것이고, include는 클래스의 모든 멤버와 메서드를 알려주는 것이다.
  • 현재 실행 중인 게임스테이트 인스턴스를 가져와서 사용할 때다른 경우들도 비슷해:근데 재밌는 건, 액터 클래스 안에서 이미 많은 기본 기능들이 포함되어 있어서 간단한 World 접근(예: 단순히 GetWorld()만 호출)은 추가 헤더 없이도 가능한 경우가 많다. 하지만 World의 특수 기능을 사용할 땐 명시적으로 헤더를 추가해야 한다고 생각하면 된다
  • PlayerController 인스턴스를 가져올 때: World->GetFirstPlayerController() GameMode 인스턴스를 가져올 때: World->GetAuthGameMode() 이런 함수들을 사용하려면 모두 "Engine/World.h"가 필요하다.
  • #include "PracticeGameStateBase.h" #include "Engine/World.h" 이렇게 World 헤더도 추가해야 한다. 왜냐면 GetWorld()->GetGameState<APracticeGameStateBase>() 같은 함수를 사용해야 한다
  • 쉽게 말해 GetGameState()는 특수함수여서 “Engine/World.h”를 헤더에 포함시켜야 한다.