Unreal EngineJuniorTechnical

Что такое класс GameMode и какова его ответственность?

GameMode — singleton-класс сервера, определяющий правила игры: какие классы использовать для Pawn, PlayerController, HUD, GameState, PlayerState; существует только на сервере и не реплицируется клиентам.

Что такое GameMode

AGameModeBase / AGameMode — это класс-«арбитр» игровой сессии. Он создаётся один раз при старте уровня и существует только на сервере (включая выделенный сервер и listen-сервер). Клиенты экземпляр GameMode не получают — для передачи данных клиентам используется AGameState.

Ответственности GameMode

  • Регистрация классов: задаёт, какие классы UE должна создавать для Pawn, PlayerController, HUD, GameState, PlayerState, SpectatorPawn.
  • Правила спавна игроков: GetDefaultPawnClassForController(), ChoosePlayerStart(), RestartPlayer().
  • Логика начала/конца матча: StartPlay(), ReadyToStartMatch(), EndMatch() (только в AGameMode, не в Base).
  • Авторизация входа: PreLogin(), Login(), PostLogin(), Logout().
  • Определение победителя, счёта, правил победы.

AGameModeBase vs AGameMode

  • AGameModeBase — минималистичная база без матчевого стейт-машины (Waiting → InProgress → End). Используйте для простых игр.
  • AGameMode добавляет MatchState (FName), события HandleMatchIsWaitingToStart, HandleMatchHasStarted, HandleMatchHasEnded, поддержку bDelayedStart.

Пример кастомного GameMode

// MyGameMode.h
#pragma once
#include "GameFramework/GameModeBase.h"
#include "MyGameMode.generated.h"

UCLASS()
class MYGAME_API AMyGameMode : public AGameModeBase
{
    GENERATED_BODY()
public:
    AMyGameMode();

    virtual void PostLogin(APlayerController* NewPlayer) override;
    virtual AActor* ChoosePlayerStart_Implementation(
        AController* Player) override;
};

// MyGameMode.cpp
#include "MyGameMode.h"
#include "MyPlayerController.h"
#include "MyCharacter.h"
#include "MyHUD.h"

AMyGameMode::AMyGameMode()
{
    DefaultPawnClass      = AMyCharacter::StaticClass();
    PlayerControllerClass = AMyPlayerController::StaticClass();
    HUDClass              = AMyHUD::StaticClass();
    // GameStateClass и PlayerStateClass тоже задаются здесь
}

void AMyGameMode::PostLogin(APlayerController* NewPlayer)
{
    Super::PostLogin(NewPlayer);
    UE_LOG(LogTemp, Log, TEXT("Player joined: %s"),
        *NewPlayer->GetName());
}

Назначение GameMode уровню

В настройках уровня (World Settings → GameMode Override) или в DefaultEngine.ini:

[/Script/EngineSettings.GameMapsSettings]
GlobalDefaultGameMode=/Script/MyGame.MyGameMode

Подводные камни

  • GameMode на клиенте: GetWorld()->GetAuthGameMode() возвращает nullptr на клиенте — обращение к нему вызовет краш.
  • Смешение GameMode и GameState: данные, которые нужны клиентам (счёт, оставшееся время), должны жить в GameState с репликацией, а не в GameMode.
  • Изменение DefaultPawnClass во время игры: смена класса не влияет на уже заспавненных пешек; нужно вручную удалить и заново заспавнить.
  • Override уровня перебивает проектные настройки: GameMode Override в World Settings имеет приоритет над DefaultEngine.ini — легко забыть при добавлении нового уровня.
  • Вызов матч-методов на AGameModeBase: методы SetMatchState, RestartGame есть только в AGameMode; попытка привести Base к Game без проверки — краш.

Common mistakes

  • Объяснять GameMode только по синтаксису, без жизненного цикла и стоимости.
  • Игнорировать ошибки, null/empty состояния, порядок инициализации или режим сборки.
  • Давать пример, который работает в демо, но ломается при изменении владельца ресурса.
  • Использовать макросы или specifier-и наугад и забывать про UObject GC.

What the interviewer is testing

  • Кандидат формулирует точную модель для GameMode, а не только определение.
  • Пример компилируем, безопасен по lifetime и соответствует версии технологии.
  • Названы trade-off, ограничения и диагностируемые симптомы ошибки.
  • Понимает границу между C++ кодом, runtime/framework metadata и editor/UI слоем.

Sources

Related topics