게임 모드 (Game Mode)와 플레이어 컨트롤러 (Player Controller) 기초
언리얼 엔진에서 게임 모드(Game Mode)와 플레이어 컨트롤러(Player Controller)는 게임의 규칙과 플레이어 입력을 관리하는 핵심 클래스입니다.
이 절에서는 이들의 역할과 C++에서의 구현 방법을 살펴보겠습니다.
AGameMode 클래스
AGameMode 클래스는 게임의 규칙, 점수 계산, 승리 조건 등을 정의합니다.
주요 기능
- 게임 시작과 종료 관리
- 플레이어 스폰 위치 결정
- 기본 폰(Pawn) 클래스 지정
- 플레이어 컨트롤러 클래스 지정
커스텀 게임 모드 구현
// MyGameMode.h
##pragma once
##include "CoreMinimal.h"
##include "GameFramework/GameModeBase.h"
##include "MyGameMode.generated.h"
UCLASS()
class MYGAME_API AMyGameMode : public AGameModeBase
{
GENERATED_BODY()
public:
AMyGameMode();
virtual void StartPlay() override;
virtual void Tick(float DeltaTime) override;
UFUNCTION(BlueprintCallable, Category = "GameMode")
void EndGame(bool bIsWinner);
private:
float GameTime;
bool bIsGameOver;
};
// MyGameMode.cpp
##include "MyGameMode.h"
##include "MyPlayerController.h"
##include "MyCharacter.h"
AMyGameMode::AMyGameMode()
{
PrimaryActorTick.bCanEverTick = true;
PlayerControllerClass = AMyPlayerController::StaticClass();
DefaultPawnClass = AMyCharacter::StaticClass();
GameTime = 0.0f;
bIsGameOver = false;
}
void AMyGameMode::StartPlay()
{
Super::StartPlay();
// 게임 시작 시 초기화 로직
}
void AMyGameMode::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
if (!bIsGameOver)
{
GameTime += DeltaTime;
// 게임 시간에 따른 로직 처리
}
}
void AMyGameMode::EndGame(bool bIsWinner)
{
bIsGameOver = true;
// 게임 종료 처리 로직
}
APlayerController 클래스
APlayerController 클래스는 플레이어의 입력을 처리하고 폰/캐릭터를 제어합니다.
주요 기능
- 플레이어 입력 처리
- 카메라 제어
- 폰/캐릭터 소유 및 제어
- HUD 및 UI 관리
커스텀 플레이어 컨트롤러 구현
// MyPlayerController.h
##pragma once
##include "CoreMinimal.h"
##include "GameFramework/PlayerController.h"
##include "MyPlayerController.generated.h"
UCLASS()
class MYGAME_API AMyPlayerController : public APlayerController
{
GENERATED_BODY()
public:
AMyPlayerController();
virtual void SetupInputComponent() override;
UFUNCTION(BlueprintCallable, Category = "Input")
void MoveForward(float Value);
UFUNCTION(BlueprintCallable, Category = "Input")
void MoveRight(float Value);
UFUNCTION(BlueprintCallable, Category = "Action")
void StartAction();
protected:
virtual void BeginPlay() override;
private:
class AMyCharacter* MyCharacter;
};
// MyPlayerController.cpp
##include "MyPlayerController.h"
##include "MyCharacter.h"
AMyPlayerController::AMyPlayerController()
{
}
void AMyPlayerController::BeginPlay()
{
Super::BeginPlay();
MyCharacter = Cast<AMyCharacter>(GetPawn());
}
void AMyPlayerController::SetupInputComponent()
{
Super::SetupInputComponent();
InputComponent->BindAxis("MoveForward", this, &AMyPlayerController::MoveForward);
InputComponent->BindAxis("MoveRight", this, &AMyPlayerController::MoveRight);
InputComponent->BindAction("Action", IE_Pressed, this, &AMyPlayerController::StartAction);
}
void AMyPlayerController::MoveForward(float Value)
{
if (MyCharacter)
{
MyCharacter->MoveForward(Value);
}
}
void AMyPlayerController::MoveRight(float Value)
{
if (MyCharacter)
{
MyCharacter->MoveRight(Value);
}
}
void AMyPlayerController::StartAction()
{
if (MyCharacter)
{
MyCharacter->StartAction();
}
}
게임 상태 관리
게임 상태는 주로 AGameStateBase 클래스를 상속받아 구현합니다.
이 클래스는 모든 플레이어와 관련된 게임의 전반적인 상태를 관리합니다.
// MyGameState.h
##pragma once
##include "CoreMinimal.h"
##include "GameFramework/GameStateBase.h"
##include "MyGameState.generated.h"
UCLASS()
class MYGAME_API AMyGameState : public AGameStateBase
{
GENERATED_BODY()
public:
UPROPERTY(Replicated, BlueprintReadOnly, Category = "GameState")
int32 Score;
UFUNCTION(BlueprintCallable, Category = "GameState")
void AddScore(int32 Points);
};
// MyGameState.cpp
##include "MyGameState.h"
##include "Net/UnrealNetwork.h"
void AMyGameState::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const
{
Super::GetLifetimeReplicatedProps(OutLifetimeProps);
DOREPLIFETIME(AMyGameState, Score);
}
void AMyGameState::AddScore(int32 Points)
{
if (HasAuthority())
{
Score += Points;
}
}
플레이어 생성 및 소멸 처리
게임 모드에서 플레이어의 생성과 소멸을 관리할 수 있습니다.
// MyGameMode.h에 추가
UCLASS()
class MYGAME_API AMyGameMode : public AGameModeBase
{
// ...
virtual void PostLogin(APlayerController* NewPlayer) override;
virtual void Logout(AController* Exiting) override;
};
// MyGameMode.cpp에 추가
void AMyGameMode::PostLogin(APlayerController* NewPlayer)
{
Super::PostLogin(NewPlayer);
// 새 플레이어 로그인 시 처리
}
void AMyGameMode::Logout(AController* Exiting)
{
Super::Logout(Exiting);
// 플레이어 로그아웃 시 처리
}
플레이어 컨트롤러와 상호작용
게임 모드와 플레이어 컨트롤러는 서로 참조하여 상호작용할 수 있습니다.
// MyPlayerController.cpp에 추가
##include "MyGameMode.h"
void AMyPlayerController::SomeFunction()
{
AMyGameMode* GameMode = Cast<AMyGameMode>(GetWorld()->GetAuthGameMode());
if (GameMode)
{
GameMode->EndGame(true);
}
}
멀티플레이어 게임에서의 역할
멀티플레이어 게임에서 게임 모드는 서버에서만 실행되며 플레이어 컨트롤러는 각 클라이언트와 서버에 존재합니다.
1. 게임 모드 (서버 전용)
- 전체 게임 규칙 관리
- 플레이어 스폰 및 연결 관리
- 게임 상태 업데이트 및 동기화
2. 플레이어 컨트롤러
- 클라이언트 : 로컬 입력 처리 및 서버로 전송
- 서버 : 클라이언트로부터 받은 입력 검증 및 처리
네트워크 관련 기능을 구현할 때는 RPC(Remote Procedure Calls)를 사용합니다.
// MyPlayerController.h에 추가
UFUNCTION(Server, Reliable, WithValidation)
void ServerPerformAction();
// MyPlayerController.cpp에 추가
void AMyPlayerController::ServerPerformAction_Implementation()
{
// 서버에서 실행될 로직
}
bool AMyPlayerController::ServerPerformAction_Validate()
{
return true; // 유효성 검사 로직
}
게임 모드와 플레이어 컨트롤러는 언리얼 엔진의 게임플레이 프레임워크에서 핵심적인 역할을 합니다.
게임 모드를 통해 전체적인 게임 규칙과 로직을 관리하고, 플레이어 컨트롤러를 통해 개별 플레이어의 입력과 상태를 처리합니다.
이 두 클래스를 효과적으로 활용하면 다양한 게임플레이 메커니즘을 구현할 수 있으며 단일 플레이어 게임에서 복잡한 멀티플레이어 게임까지 확장 가능한 구조를 만들 수 있습니다.