Game State (Game State Base) в Unreal Engine

Друзья, приветствую, с Вами Будуев Антон. В этой статье мы обсудим класс Game State (Game State Base) в Unreal Engine (UE5, UE4), который отвечает за хранение и управление состоянием игры.

Вскоре выйдет моя бесплатная книга по Blueprints для Unreal Engine в PDF формате. Как она выйдет, рекомендую её скачать, чтобы Вы детально изучили блюпринты Анрил Энджин.

Game State

Любая игра строится на наборе правил, которые определяют её суть и логику. Когда в ходе игрового процесса происходят события, связанные с этими правилами, возникает необходимость не только отслеживать их, но и своевременно информировать обо всех изменениях всех участников.

В многопользовательских играх эта задача усложняется, так как в неё вовлечено множество игроков, каждый из которых должен получать актуальную, синхронизированную и единую информацию в любой момент времени.

В Unreal Engine для решения этих задач служит класс Game State. Именно он отвечает за хранение и синхронизацию глобального состояния игры, обеспечивая всех игроков (включая удалённых клиентов) одинаковыми и своевременными данными об изменениях игрового мира.

Game State — класс в Unreal Engine, который управляет глобальным состоянием игры. Он создается сервером (конкретно — объектом Game Mode) и существует как на сервере, так и на клиентах, при этом его данные полностью реплицируются. Это значит, что состояние, хранящееся в Game State, одинаково доступно и синхронизировано для всех игроков и клиента.

 

Таблица распределения классов фреймворка Unreal Engine (UE4, UE5) по тому, где существует объект этого класса. В данном случае Game State существует как на сервере, так и на всех клиентах.
Таблица распределения классов фреймворка Unreal Engine (UE4, UE5) по тому, где существует объект этого класса. В данном случае Game State существует как на сервере, так и на всех клиентах.

Состояние игры включает в себя набор данных и логику, которые охватывают всю игровую сессию и касаются всех игроков одновременно. Среди таких данных могут быть:

  • результаты команд,
  • игровые цели и задачи,
  • список подключённых игроков,
  • оставшееся время текущего раунда,
  • и другая важная информация, общая для всей сессии.

Однако класс GameState не предназначен для хранения информации, специфичной для отдельного игрока — например, его здоровье, индивидуальное количество очков или уникальная статистика. Для этих целей в Unreal Engine существует отдельный класс Player State, который создаётся индивидуально для каждого игрока и служит хранилищем именно персональных игровых данных.

GameState, в свою очередь, содержит специальное свойство Player Array — массив ссылок на все объекты Player State, которые существуют в текущей игре. Через этот массив он хранит и управляет списком состояний всех игроков, обеспечивая централизованное и синхронизированное с клиентами представление о каждом участнике матча.

Таким образом, архитектура Unreal Engine чётко разделяет глобальное состояние всего матча (GameState) и локальное состояние каждого участника (Player State), обеспечивая гибкое и эффективное управление данными в мультиплеерных проектах.

Game State Base

В Unreal Engine существуют 2 вида класса состояния игры:

  • Game State Base,
  • Game State.

Game State Base — базовый класс, управляющий глобальным состоянием игры. Он создается сервером (объектом Game Mode Base), существует как на сервере, так и на клиентах и полностью реплицируется. Представляет минимальный набор данных состояния игры, которые нужны для синхронизации в мультиплеерной сессии. Подходит для любых типов игр, где необходима базовая синхронизация состояния.

Game State — наследник Game State Base, расширяющий родительский базовый класс функционалом для матч-ориентированных игр. В нём реализована логика состояний матча (Match State), управление состояниями начала, прогресса и завершения матча, а также дополнительные поля и методы для работы с матчами. Используется, когда игра построена по модели матча — то есть с четкими фазами игры, временем раунда, победительными условиями и т.п.

Выбор между классами Game State Base и Game State тесно связан с используемым в проекте классом игрового режима — Game Mode. Если в проекте в Unreal Engine задействован GameModeBase, то для состояния игры рекомендуется использовать базовый класс GameStateBase. Напротив, если применяется класс GameMode, стоит использовать соответствующий класс состояния игры — GameState, который расширяет базовый класс состояния игры дополнительными возможностями для матчевых игр.

Перевод официальной справки:

Game State Base — управляет глобальным состоянием игры и создаётся посредством Game Mode Base. Он существует как на сервере, так и на клиенте и полностью реплицируется.

Game State — это подкласс Game State Base, ведущий себя как игра, основанная на матчах в многопользовательском режиме. Он тесно связан с функциональностью Game Mode.

Основная функциональность класса состояния игры

Game State Base

  • Global State Management — управление глобальным состоянием игры. Централизованное хранение и поддержка основного состояния игрового мира (GameModeClass — класс игрового режима, SpectatorClassкласс наблюдателя, PlayerArray список всех игроков, ReplicatedHasBegunPlay флаг начала игры).
  • Replication and Synchronization — репликация и синхронизация данных. Репликация важных игровых данных (список игроков, классы GameMode и Spectator) от сервера ко всем клиентам с обработкой уведомлений об обновлениях.
  • Player State Handling — управление состояниями игроков. Поддержка массива Player Array, включающего объекты Player State, с возможностью добавления, удаления и поиска состояния игрока по уникальному сетевому идентификатору.
  • Server Time Management — управление временем игрового мира сервера. Отслеживание и плавная синхронизация серверного игрового времени с клиентами с частотой обновления, обеспечивающая временную согласованность в игре.
  • Game Lifecycle Integration — интеграция с жизненным циклом игры. Отслеживание и информирование о важных статусах игры: начала игрового мира (HasBegunPlay), начала матча (HasMatchStarted) и его окончания (HasMatchEnded, по умолчанию всегда False).
  • Seamless Travel Support — поддержка бесшовных переходов между уровнями. Обеспечение корректного переноса и пометки состояний игроков при смене карт без потери данных (Seamless Travel).
  • Player-Specific Timers and Delays — персональные временные параметры игроков. Определение времени старта для отдельного игрока (GetPlayerStartTime) и задержек перед его возрождением (GetPlayerRespawnDelay), предоставляющее точки расширения для кастомной логики.

Game State

  • Match State — реализация хранения состояний матча с возможностью отслеживать текущий и предыдущий статусы игры, обеспечивая переходы между ними и вызовы соответствующих обработчиков (MatchStateхранит текущее состояние матча, 
    PreviousMatchStateхранит предыдущее состояние, SetMatchState устанавливает новое состояние).
  • Match Lifecycle Events — обработка событий жизненного цикла матча. Обработка ключевых событий матча: ожидание начала (WaitingToStart), начало (InProgress), окончание (WaitingPostMatch), и уход с карты (LeavingMap).
  • Elapsed Time Tracking — отслеживание прошедшего времени матча. Учёт и репликация времени, прошедшего с момента старта матча, с уведомлением клиентов о его изменениях для синхронизации интерфейса и логики.
  • Match State Replication — репликация состояния матча. Репликация переменной состояния матча (MatchState) и механизмы уведомления клиентов при её изменении для правильного обновления локальной логики.
  • Match Control Functions — внутренние функции управления матчем. Методы для изменения состояния матча (SetMatchState), проверки текущего хода игры (IsMatchInProgress) и обработки стандартного таймера обновления (DefaultTimer).
  • Overridden Lifecycle Integration — переопределённая интеграция с жизненным циклом игры. Переопределение базовых функций для учёта состояния матча (HasMatchStarted, HasMatchEnded, HandleBeginPlay) и расчёта игровых параметров, таких как время старта и задержки возрождения игрока.
  • Timer Management — управление таймерами матча. Реализация внутреннего таймера (TimerHandle_DefaultTimer) для периодического обновления логики матча и синхронизации.

Наследование классов

Класс Game State наследуется от Game State Base расширяя его функционалом для матч-ориентированных игр. Game State Base, в свою очередь, наследуется от класса Info, добавляя главным образом функциональность хранения и управления состоянием игры. Сам же класс Info наследуется от Actor (базовый класс для объектов, размещаемых на игровом уровне).

* Info — абстрактный класс для Акторов, которые не имеют физического представления в мире и используются для хранения информации и управления игровыми системами.

Общее наследование классов состояния игры: Actor > Info > Game State Base > Game State
Общее наследование классов состояния игры: Actor > Info > Game State Base > Game State

Как создать и подключить Game State

Для создания нового класса состояния игры перейдите в Content Browser и вызовите контекстное меню, щелкнув правой кнопкой мыши по пустой области браузера. В появившемся меню выберите пункт Blueprint Class. Затем в окне Pick Parent Class в строке поиска введите «Game State» и нажмите кнопку Select. В результате в текущей папке Content Browser будет создан ассет базового класса состояния игры.

Создание blueprint класса Game State Base в Unreal Engine (UE4, UE5)
Создание blueprint класса Game State Base в Unreal Engine (UE4, UE5)

Чтобы подключить класс состояния игры (GameState) в Unreal Engine (UE4, UE5), необходимо использовать ассет GameMode. Для этого откройте используемый в проекте класс GameMode. Перейдите в меню Class Defaults, затем во вкладку Details и найдите раздел Classes. В этом разделе найдите параметр Game State Class и из выпадающего списка выберите ваш собственный класс состояния игры.

Установка пользовательского класса GameState в GameMode
Установка пользовательского класса GameState в GameMode

Если в вашем проекте ещё нет собственного Game Mode, создайте его аналогично процессу создания класса состояния игры: через Blueprint Class с выбором родительского класса Game Mode. Затем подключите этот Game Mode в настройках проекта:
Edit / Project Settings / Maps & Modes / Default GameMode.

Подключение пользовательского класса GameMode
Подключение пользовательского класса GameMode

Как в Unreal Engine получить текущий Game State. Функция Get Game State

Blueprint-функция Get Game State
Blueprint-функция Get Game State

Blueprint-функция Get Game State позволяет из любого класса в Blueprint получить ссылку на текущий экземпляр состояния игры. Эта функция возвращает указатель (ссылку) на объект класса GameStateBase — базового класса, управляющего глобальным состоянием игры. Если объект состояния игры ещё не создан (например, до завершения инициализации уровня), функция возвращает Null.

Поскольку возвращаемый тип — GameStateBase, он предоставляет доступ только к базовому набору функций и переменных, общих для всех состояний игры. Чтобы получить доступ к пользовательским переменным и функциям, реализованным в кастомном классе состояния игры (например, BP_CustomGameState), необходимо выполнить приведение типа (Cast) к этому классу.

На схеме ниже показан пример того, как получить текущий объект Game State.

  1. Функция Get Game State возвращает ссылку на объект типа GameStateBase.
  2. С помощью каста Cast To BP_CustomGameState выполняется приведение типа. Если текущий GameState действительно является экземпляром BP_CustomGameState, каст завершится успешно.
  3. Результат каста сохраняется в переменную As BP Custom Game State, которая теперь содержит ссылку на пользовательский класс состояния игры с доступом ко всем его полям и методам.

Скриншот

Получаем текущий «BP_CustomGameState» с использованием каста «Cast to BP_CustomGameState»
Получаем текущий «BP_CustomGameState» с использованием каста «Cast to BP_CustomGameState»

Код на BlueprintUE

Если код отображается без связей, нажмите сверху кода на кнопку «Graph» Если код отображается без связей, нажмите сверху кода на кнопку "Graph"


Также можно получить доступ к пользовательскому классу GameState через Blueprint Interface — систему интерфейсов Unreal Engine. Этот подход считается более предпочтительным, хотя и несколько сложнее в реализации. Для его использования необходимо создать интерфейс с функцией, например, Get Custom Game State, и реализовать эту функцию внутри пользовательского класса состояния игры — например, в BP_CustomGameState.

Таким образом, обращаясь к объекту состояния игры через интерфейс, сокращается зависимость от конкретного класса и упрощается поддержка и расширение проекта, что обеспечивает более чистую архитектуру взаимодействия между объектами.

Скриншот

Получаем текущий «BP_CustomGameState» с использованием пользовательского интерфейса «Get Custom Game State»
Получаем текущий «BP_CustomGameState» с использованием пользовательского интерфейса «Get Custom Game State»

Код на BlueprintUE

Если код отображается без связей, нажмите сверху кода на кнопку «Graph» Если код отображается без связей, нажмите сверху кода на кнопку "Graph"


Blueprint-переменные Game State (Base)

Game State Base

Переменные класса Game State Base
Переменные класса Game State Base
  1. Game Mode Class — хранит класс игрового режима, установленный на сервере. Служит для синхронизации и передачи клиентам информации о текущем типе игрового режима.
  2. Authority Game Mode — хранит указатель (ссылку) на серверный экземпляр текущего игрового режима, доступный только на сервере (авторитете) и недоступный клиентам (для клиентов возвращает значение Null). Это ключевой объект, управляющий правилами и логикой игры на сервере.
  3. Spectator Class — хранит класс, используемый для наблюдателей (Spectator Pawn), назначаемый объектом Game Mode Base.
  4. Player Array — хранит массив указателей (ссылок) на объекты Player State всех игроков в игре, который поддерживается как на сервере, так и на клиентах. Данный массив служит централизованным хранилищем глобальной информации о состоянии игроков. Массив не реплицируется напрямую, но его содержимое синхронизируется через репликацию самих объектов Player State. Сам массив Player Array автоматически поддерживается движком (сервером) при подключении и отключении игроков. Объекты Player State добавляется движком в массив и удаляется из него. Разработчикам, как правило, не нужно вручную модифицировать этот массив, а лишь читать из него данные.

Game State

Переменные класса Game State
Переменные класса Game State
  • Match State — реплицируемое от сервера на всех клиентов свойство, содержащее текущий статус матча (игровой стадии):
    • Entering Map — происходит загрузка карты, Акторы ещё не обновляются.
    • Waiting To Start — Акторы уже обновляются (Tick), но матч ещё не начался.
    • In Progress — идет нормальный игровой процесс, основное состояние матча.
    • Waiting Post Match — матч завершён, игроков новых не принимают, но Акторы продолжают работать.
    • Leaving Map — происходит выход с карты для перехода на новое место.
    • Aborted — матч прерван из-за проблем, продолжить игру невозможно.
  • Previous Match State — вспомогательное свойство, хранящее имя предыдущего состояния матча. Помогает корректно обрабатывать множественные переходы состояний за один кадр и синхронизировать логику изменения матч-стейтов.
  • Elapsed Time — целочисленное реплицируемое свойство, которое хранит время, прошедшее с начала матча. Это свойство синхронизируется между сервером и клиентами и используется для отслеживания времени матча в режиме мультиплеера.
  • остальные переменные унаследованы от Game State Base.

Blueprint-функции класса Game State Base

Blueprint-функции класса Game State Base
Blueprint-функции класса Game State Base
  • Get Player Respawn Delay — возвращает количество времени, которое игрок должен провести в ожидании (Dead Time) перед тем, как он сможет возродиться (Respawn) после смерти.
  • Get Player Start Time — возвращает время, которое следует использовать в качестве момента старта игрока.
  • Get Server World Time Seconds — возвращает текущее синхронизированное игровое время сервера с учётом корректировок, доступное как на сервере, так и на клиентах.
  • Has Begun Play — возвращает значение True, если в игровом мире был вызван метод BeginPlay() у Акторов, то есть игра официально «запущена» и игровые объекты начали свою работу.
  • Has Match Ended — указывает, считается ли матч завершённым. В Game State Base — реализации у данной функции нет и по умолчанию возвращает False. В классе Game State функция переопределена и возвращает True, если состояние матча соответствует состоянию после окончания (Waiting Post Match, Leaving Map).
  • Has Match Started — возвращает значение True, если матч для данного игрового мира уже начался (т.е. было вызвано событие начала матча).

Практика в Unreal Engine №1. Подсчёт общего количества игроков, подключённых к игре. Массив «Player Array».

Задача: при подключении очередного игрока к многопользовательской игре вывести общее количество игроков, подключённых к игре.

Задача в Unreal Engine: вывести общее количество игроков, подключённых к игре.
Задача в Unreal Engine: вывести общее количество игроков, подключённых к игре.
  1. Весь код решения данной задачи мы будем описывать в Event Graph пользовательского класса игрового режима CustomGameMode. Так как в этом классе имеется событие Event OnPostLogin, которое вызывается в момент подключения нового игрока к текущей игре. А это именно то, что нам и нужно. Ведь по условию задачи необходимо подсчитать количество игроков именно в момент подключения нового игрока. Итак, весь код мы будем запускать при вызове события Event OnPostLogin.
  2. В классе Game State, который мы рассматриваем в данной статье, имеется специальный массив Player Array. Этот массив содержит актуальные объекты Player State, каждый из которых представляет отдельного подключённого игрока. Подсчитав количество элементов в данном массиве, мы сможем определить количество текущих игроков в игре.
  3. Итак, получим доступ к объекту класса Game State через функцию Get Game State.
  4. Далее, из возвращённого объекта GameState получим массив PlayerState, вызвав функцию Get Player Array.
  5. Подсчитаем количество элементов в данном массиве функцией LENGTH.
  6. Ну и на последнем шаге напечатаем на экране функцией Print String количество элементов массива. А это будет не что иное, как количество текущих игроков. И благодаря событию Event OnPostLogin данный текст будет выводиться на экран только тогда, когда к игре подключится очередной новый игрок.

Скриншот

Практика в Unreal Engine №1. Подсчёт общего количества игроков, подключённых к игре. Массив «Player Array»
Практика в Unreal Engine №1. Подсчёт общего количества игроков, подключённых к игре. Массив «Player Array»

Код на BlueprintUE

Если код отображается без связей, нажмите сверху кода на кнопку «Graph» Если код отображается без связей, нажмите сверху кода на кнопку "Graph"


Практика в Unreal Engine №2. Система отслеживания счета в Game State для нескольких команд многопользовательской игры.

Задача: создать систему, позволяющую отслеживать счёт, сохранять очки и обновлять их для нескольких команд в многопользовательской командной игре.

Согласно условиям задачи, у нас есть несколько команд, и для каждой из них ведётся счёт. Эту информацию необходимо где-то сохранять и обрабатывать. Наиболее подходящим решением для этого является класс Game State (состояние игры), так как счёт каждой команды напрямую отражает текущее состояние игры.

Поэтому далее будем реализовывать код в Event Graph, используя пользовательский класс CustomGameState.

  1. Поскольку в игре может быть несколько команд, то удобнее всего хранить счет (Score) в массиве. Для этого создадим целочисленный массив ScoreTeam, где каждый элемент будет представлять собой текущий счет для соответствующей команды. Порядковый номер элемента массива при этом будет соответствовать номеру команды. Таким образом, в массиве ScoreTeam текущий счет для команды с номером 0 будет храниться под индексом [0].Массив "ScoreTeam"
  2. Создадим пользовательское событие Add Score, которое будет активироваться в момент начисления очков конкретной команде. В качестве параметров для этого события определим два целочисленных значения: Number Team (int) — номер команды (0, 1, 2 и так далее)Count Points (int) — количество начисляемых очков.
  3. Затем воспользуемся нодой Switch Has Authority, чтобы продолжить процесс только через выходной пин Authority. Таким образом код будет отрабатывать только на сервере. Если же событие инициируется на клиенте, то код выполнен не будет.
  4. При помощи функции Set Array Elem внесём новое значение счёта для определённой команды в массив ScoreTeam. Чтобы это сделать, необходимо передать номер этой команды (Number Team) в качестве параметра Index.
  5. Теперь осталось только вычислить новое значение счёта. Для этого воспользуемся нодой GET из массива ScoreTeam, передав в эту ноду номер команды. Таким образом, нода GET возвратит текущий счёт для команды под номером Number Team.
  6. Далее добавим к текущему счету количество очков, переданное в параметре Count Points события Add Score. Затем отправим полученное новое значение счета для команды Number Team в параметр Item функции Set Array Elem. Где она, в свою очередь, перезапишет этот счёт в массиве ScoreTeam.

Скриншот

Практика в Unreal Engine №2. Система отслеживания счета для нескольких команд в многопользовательской игре.
Практика в Unreal Engine №2. Система отслеживания счета для нескольких команд в многопользовательской игре.

Код на BlueprintUE

Если код отображается без связей, нажмите сверху кода на кнопку «Graph» Если код отображается без связей, нажмите сверху кода на кнопку "Graph"


Таким образом, в классе GameState мы создали систему, которая позволяет отслеживать счёт, сохранять очки и обновлять их для нескольких команд в многопользовательской командной игре.

Совет. Вскоре выйдет моя бесплатная книга по Blueprints для Unreal Engine в PDF формате. Как она выйдет, рекомендую её скачать, чтобы Вы детально изучили блюпринты Анрил Энджин.


наш Телеграм канал

Оцените статью
( 4 оценки, среднее 5 из 5 )
Поделитесь этой статьей со своими знакомыми в социальных сетях, возможно, эта статья кому-то будет полезна
Unreal Engine - это просто
Добавить комментарий

Нажимая на кнопку "Отправить комментарий", я даю согласие на обработку персональных данных и принимаю политику конфиденциальности.