UE5 Gameplay Framework 구조 완전 이해
Unreal Engine의 Gameplay Framework는 게임 규칙과 플레이어 상호작용을 체계화하는 클래스 계층입니다. 각 클래스의 역할과 생성 순서를 이해하면 기능을 올바른 위치에 배치할 수 있습니다.
1. 클래스 역할 요약
섹션 제목: “1. 클래스 역할 요약”| 클래스 | 존재 위치 | 주요 역할 |
|---|---|---|
AGameModeBase | 서버 전용 | 게임 규칙, 플레이어 스폰 정책 |
AGameStateBase | 서버 + 모든 클라이언트 | 게임 공유 상태 (점수, 타이머) |
APlayerController | 서버 + 해당 클라이언트 | 입력 처리, 카메라 제어 |
APlayerState | 서버 + 모든 클라이언트 | 플레이어별 공개 상태 (이름, 점수) |
APawn / ACharacter | 서버 + 모든 클라이언트 | 월드 내 표현(물리, 렌더링) |
2. GameMode — 게임 규칙
섹션 제목: “2. GameMode — 게임 규칙”UCLASS()class AMyGameMode : public AGameModeBase{ GENERATED_BODY()public: AMyGameMode();
// 플레이어 스폰 위치 결정 virtual AActor* FindPlayerStart_Implementation( AController* Player, const FString& IncomingName) override;
// 플레이어 사망 처리 void OnPlayerDied(AController* Controller);
// 승리 조건 체크 void CheckWinCondition();
private: int32 FragLimit = 10;};
// MyGameMode.cppAMyGameMode::AMyGameMode(){ DefaultPawnClass = AMyCharacter::StaticClass(); PlayerControllerClass = AMyPlayerController::StaticClass(); GameStateClass = AMyGameState::StaticClass(); PlayerStateClass = AMyPlayerState::StaticClass();}3. GameState — 공유 게임 상태
섹션 제목: “3. GameState — 공유 게임 상태”UCLASS()class AMyGameState : public AGameStateBase{ GENERATED_BODY()public: UPROPERTY(Replicated) int32 BlueTeamScore;
UPROPERTY(Replicated) int32 RedTeamScore;
UPROPERTY(Replicated) float RemainingTime;
virtual void GetLifetimeReplicatedProps( TArray<FLifetimeProperty>& OutLifetimeProps) const override;};
void AMyGameState::GetLifetimeReplicatedProps( TArray<FLifetimeProperty>& OutLifetimeProps) const{ Super::GetLifetimeReplicatedProps(OutLifetimeProps); DOREPLIFETIME(AMyGameState, BlueTeamScore); DOREPLIFETIME(AMyGameState, RedTeamScore); DOREPLIFETIME(AMyGameState, RemainingTime);}4. PlayerController — 입력과 카메라
섹션 제목: “4. PlayerController — 입력과 카메라”UCLASS()class AMyPlayerController : public APlayerController{ GENERATED_BODY()protected: virtual void BeginPlay() override; virtual void SetupInputComponent() override;
public: // 서버 RPC — 공격 요청 UFUNCTION(Server, Reliable) void ServerRequestAttack();
// 클라이언트 RPC — HUD 갱신 UFUNCTION(Client, Reliable) void ClientUpdateHUD(int32 NewHealth);};
void AMyPlayerController::SetupInputComponent(){ Super::SetupInputComponent();
if (UEnhancedInputComponent* EIC = Cast<UEnhancedInputComponent>(InputComponent)) { EIC->BindAction(AttackAction, ETriggerEvent::Triggered, this, &AMyPlayerController::ServerRequestAttack); }}5. PlayerState — 플레이어 공개 정보
섹션 제목: “5. PlayerState — 플레이어 공개 정보”UCLASS()class AMyPlayerState : public APlayerState{ GENERATED_BODY()public: UPROPERTY(Replicated) int32 Kills;
UPROPERTY(Replicated) int32 Deaths;
UPROPERTY(Replicated) FString TeamName;
void AddKill(); void AddDeath();};6. 생성 순서 (서버 기준)
섹션 제목: “6. 생성 순서 (서버 기준)”1. GameMode 생성 (서버 전용)2. GameState 생성 및 복제 시작3. 플레이어 접속 → PlayerController 생성4. PlayerState 생성 및 복제5. GameMode::SpawnDefaultPawnFor() → Pawn 스폰6. PlayerController::Possess(Pawn)7. 올바른 기능 배치 기준
섹션 제목: “7. 올바른 기능 배치 기준”"이 데이터가 모든 클라이언트에 필요한가?" → Yes: GameState 또는 PlayerState → No (해당 플레이어만): PlayerController
"이것은 게임 규칙인가?" → Yes: GameMode (서버 전용)
"이것은 물리/시각 표현인가?" → Yes: Pawn / CharacterGameplay Framework는 “누가 이 정보를 알아야 하는가”를 기준으로 설계되었습니다. GameMode는 규칙을 강제하고, GameState/PlayerState는 모든 클라이언트와 상태를 공유하며, PlayerController는 해당 플레이어의 입력과 UI를 담당합니다. 기능을 올바른 클래스에 배치해야 네트워크 복제가 자연스럽게 동작합니다.