게임 개발 초기, 특히 로비, 캐릭터 선택, 실제 게임 플레이 등 다양한 단계를 가진 게임에서는 GameMode와 GameState의 역할을 명확히 하는 것이 중요하다. 여기서는 메인 메뉴, 싱글 플레이 로비, 튜토리얼 단계를 위한 GameMode/GameState 설계 과정을 정리한다.
1. 기본 구조: ACSGameModeBase와 ACSGameStateBase
먼저 공통 로직을 처리할 기반 클래스를 정의한다.
ACSGameModeBase (AGameMode 상속):MatchType (Single, Coop, Versus), MatchPhase (Waiting, Playing, Finished) 같은 기본 상태 관리.BeginPlay에서 GameInstance로부터 MatchType을 읽어 InitMatchLogic 호출.PostLogin 등 기본적인 플레이어 관리 오버라이드 포인트 제공.HandleStartGame, HandleEndGame으로 MatchPhase 변경 및 GameState에 전파 (SetMatchPhase 함수).ACSGameStateBase (AGameStateBase 상속):MatchPhase 등 리플리케이트되어야 하는 게임 전체 상태 저장.// CSGameModeBase.h 예시 일부
UCLASS()
class CS_API ACSGameModeBase : public AGameMode
{
// ... MatchType, MatchPhase 변수 ...
virtual void BeginPlay() override;
virtual void InitMatchLogic(); // MatchType 따라 다른 초기화 호출
void SetMatchPhase(EMatchPhase NewPhase); // GameState에도 반영
};
// CSGameStateBase.h 예시 일부
UCLASS()
class CS_API ACSGameStateBase : public AGameStateBase
{
UPROPERTY(Replicated) EMatchPhase MatchPhase;
// ...
};
2. 메인 메뉴: CSMainMenuGameMode
MatchType에 따라 다음 레벨 로드.AGameMode 직접 상속 (Base 불필요).PlayerController의 책임. GameMode는 UI 클래스를 가지지 않는다.TryStartMatch 함수: GameInstance의 MatchType 확인 후 OpenLevel 호출 (튜토리얼 또는 로비).PostLogin: 플레이어 접속 시 로그 남기기 외 특별한 역할 없음 (UI는 PlayerController가 BeginPlay에서).3. 싱글 플레이 로비/캐릭터 선택: CSSingleLobbyGameMode, CSSingleLobbyGameState
CSSingleLobbyGameMode (AGameMode 상속):GameStateClass = ACSSingleLobbyGameState::StaticClass(); 설정.RequestStartTutorial: PlayerController로부터 호출됨. 핵심 역할은 아래 두 가지.TSubclassOf<APawn>)를 GameInstance 또는 PlayerState에 저장.UGameplayStatics::OpenLevel로 튜토리얼 레벨 로드.CSSingleLobbyGameState (AGameState 상속):AvailableCharacterClasses) 저장 및 리플리케이트 가능.4. 튜토리얼: CSTutorialGameMode, CSTutorialGameState
CSTutorialGameMode (ACSGameModeBase 상속):GameStateClass = ACSTutorialGameState::StaticClass(); 설정.GetDefaultPawnClassForController: (구현 필요) 로비에서 GameInstance/PlayerState에 저장된 SelectedCharacterClass 정보를 읽어와 리턴. 실패 시 FallbackDefaultPawnClass 사용.HandleStartingNewPlayer, RestartPlayer: 플레이어 스폰 후 MakePlayerInvulnerable 호출.MakePlayerInvulnerable: 플레이어 Pawn의 SetCanBeDamaged(false) 호출하여 무적 처리.PlayerEnteredStageTransitionZone: (레벨 액터 호출 필요) 레벨 내 트리거 액터가 호출하면 StageLevelName에 지정된 다음 레벨 로드.CSTutorialGameState (ACSGameStateBase 상속):CurrentObjectiveText (FText, ReplicatedUsing=OnRep): 현재 목표 텍스트 저장 및 클라이언트 전파.bIsTutorialComplete (bool, Replicated): 튜토리얼 완료 여부 플래그.SetCurrentObjectiveText, CompleteTutorial: 서버 전용 함수 (GameMode가 호출).OnRep_CurrentObjectiveText: 클라이언트에서 목표 텍스트 변경 감지 시 호출됨. (UI 업데이트 로직 구현 필요).5. 연결 흐름 및 핵심 구현 포인트
PlayerController) -> 서버 RPC (Server_RequestStartTutorial, 선택 캐릭터 정보 전달) -> ACSPlayerController.ACSPlayerController) -> CSSingleLobbyGameMode::RequestStartTutorial 호출.CSSingleLobbyGameMode -> 선택 정보 저장 (GameInstance 또는 PlayerState의 SelectedCharacterClass 변수 구현 필요) -> OpenLevel.CSTutorialGameMode::GetDefaultPawnClassForController -> 저장된 정보 읽기 (GameInstance/PlayerState의 SelectedCharacterClass 변수 구현 필요) -> Pawn 클래스 리턴.HandleStartingNewPlayer/RestartPlayer -> Pawn 스폰 및 SetCanBeDamaged(false).CSTutorialGameMode -> 튜토리얼 진행 -> CSTutorialGameState::SetCurrentObjectiveText 호출.CSTutorialGameState -> CurrentObjectiveText 변경 및 리플리케이트.CSTutorialGameState -> OnRep_CurrentObjectiveText 호출.OnRep_CurrentObjectiveText -> 로컬 ACSPlayerController의 UpdateTutorialObjectiveUI 함수 호출 (구현 필요).ACSPlayerController -> TutorialWidgetInstance의 텍스트 업데이트 함수 호출 (구현 필요).BP_StageTransitionTrigger 등 구현 필요) -> 플레이어 감지 -> CSTutorialGameMode::PlayerEnteredStageTransitionZone 호출.CSTutorialGameMode -> OpenLevel (미리 설정된 StageLevelName).