Описание FSM
Система FSM (Finite State Machine) предназначена для централизованного управления состояниями игровых объектов, обеспечивая чёткое и последовательное выполнение действий на основе различных входящих запросов от управляющих подсистем (AI, пользовательские команды, физика и другие). Цель FSM — разрешать конфликтующие запросы и выбирать наиболее подходящее состояние объекта для поддержания логической согласованности и плавности анимаций, а также корректной работы игровых механик.
Основные функции FSM:
приём запросов от внешних управляющих систем;
разрешение конфликтов между запросами;
выбор допустимого перехода и обновление текущего состояния юнита;
передача состояния в другие системы: анимации, поведение, скрипты и пр.
Компоненты FSM
Состояние
Состояние (state) представляет собой описание текущей позиции или действия юнита (например: stand, walk, fire, blown_away). В каждый момент времени юнит может находиться только в одном состоянии. Состояния являются узлами в FSM-графе переходов между состояниями.
Каждое состояние:
имеет уникальное имя;
имеет как минимум один тег;
связи между состояниями формируют возможные переключения между состояниями.
Теги
Тег (tag) — это текстовая метка, назначаемая состоянию. Тег выполняет две функции:
позволяет внешним системам понять, в каком логическом состоянии находится юнит;
определяет, какой запрос должен привести к данному состоянию. Пример: одно из доступных состояний с тегом fire будет выбрано в ответ на запрос fire.
Запросы
Запрос (request)— это внешняя команда, поступающая от управляющих подсистем игры (AI, пользовательского ввода, физики и др.), которая инициирует в рамках FSM процесс перевода управляемого объекта в новое состояние.
В отличие от сигнала, который является мгновенным событием, запрос может сохраняться активным в течение некоторого времени до тех пор, пока либо не будет обработан, либо не будет отменён.
Каждый запрос связан как минимум с одним состоянием FSM через одноимённый тег состояния. Наличие тега позволяет FSM идентифицировать, что данное состояние способно обработать указанный запрос при выполнении дополнительных условий перехода.
Результат обработки запроса зависит от:
текущего состояния управляемого объекта;
приоритета запроса;
правил переходов, описанных в FSM-графе.
FSM поддерживает несколько типов запросов.
Таблица типов запросов приведена для ознакомления, с целью целостного восприятия работы конечного автомата (FSM) в Gem RTS.
Switch
Запрос этого типа вызывается в коде однократно и ожидает в очереди возможности для выполнения. После выполнения удаляется.
Команда “Лечь”
Job
Тип запроса, вызываемый из кода каждый квант после перевода юнита в целевое FSM-состояние. Удерживает юнита в этом состоянии, пока запрос остаётся активным. Запрос данного типа сбрасывается при отсутствии его вызова из кода дольше, чем указано в параметре duration
, или при поступлении более приоритетного запроса.
При сбросе запускает запрос типа Switch
из блока exit
в описании FSM, если юнит всё ещё находится в целевом состоянии.
Команда “Ремонтировать”
Action
Запрос данного типа вызывается из кода каждый квант до возможности перехода юнита в целевое состояние; при срабатывании переводит юнита в целевое состояние для выполнения действия, после чего удаляется. Если запрос не вызывался хотя бы один квант, то он удаляется без выполнения.
Команда “Бросить гранату”
State
Запрос вызывается в коде однократно, после чего происходит переход в целевое состояние. Состояние сохраняется, пока не будет отменен или не придёт более приоритетный запрос.
Спрятать оружие, если оно воткнулось в стену
Система запросов и тегов используется в движке для координации работы различных игровых подсистем. Часть запросов и тегов предопределена в исходном коде. Некоторые состояния и теги могут быть определены в конфигурационных файлах (например, файлы описания элементов интерфейса, предметов инвентаря, оружия), что позволяет модифицировать и расширять поведение игровых объектов без изменений в коде, обеспечивая гибкость в настройке игровых механик.
Подмножества состояний
FSM-подмножество (Subset) — это компонент FSM, задающий ограничения на переходы, исключая из рассмотрения состояния, несовместимые с текущим состоянием объекта.
Пример: Если юнит удерживает канистру, FSM-подмножество исключает состояния лежать, сидеть и ремонтировать, поскольку выполнение этих действий несовместимо с текущим состоянием объекта.
Обработка запроса в FSM
Этапы процесса обработки запроса:
Выбор FSM-подмножества В соответствии с текущим состоянием юнита обработчик состояний выбирает FSM-подмножество, которое ограничивает выборку доступных для перехода состояний.
Анализ приоритетов При поступлении нескольких запросов одновременно FSM анализирует их приоритеты. Запрос с наивысшим приоритетом имеет преимущество при выборе нового состояния. Равнозначные по приоритету запросы разрешаются согласно порядку поступления.
Проверка доступности перехода:
Задан ли графом FSM переход в целевое состояние из текущего состояния.
Выполнены ли условия (например, наличие определённых тегов или дополнительных параметров запроса).
Результат обработки запроса FSM выбирает ближайшее доступное по графу состояние, соответствующее тегу запроса, независимо от того, находится ли оно в прямой связи с текущим состоянием — переключение состояний может происходить через промежуточные состояния.
Типичный сценарий работы FSM
Стартовая позиция: юнит находится в состоянии ожидания (idle). Начинается бой: юнит обнаруживает противника, получает приказ от AI атаковать врага и одновременно команду от игрока «окопаться». Рядом с юнитом происходит взрыв, взрывная волна достаточной силы, чтобы отбросить юнита и нанести ему урон. Запросы на изменение состояния юнита отправляются в FSM. Поскольку юнит не может одновременно в нескольких состояниях (окапываться, атаковать, реагировать на взрыв, лечиться или погибать), FSM разрешает этот конфликт, выбирая наиболее приоритетное и допустимое состояние.
При активации нового состояния объекта обработчик состояний передает состояние в игровые системы, а также запускает скрипты и анимации, соответствующие этому состоянию.
При выходе объекта из состояния обработчик состояний информирует игровые системы об окончании состояния, останавливает воспроизведение соответствующих анимаций и эффектов, а также связанных с состоянием процессов и скриптов, после чего очищает ресурсы.
Компоненты конфигурации FSM
Логика конечного автомата описывается в .def файле юнита с использованием блока fsm
:
Формат записи
{fsm "name" ... }
где
"name"
— имя FSM.
Список запросов
Полное описание запросов доступно в исходном коде. В конфигурационный файл выносятся лишь параметры, доступные для настройки.
С помощью блоков параметра request
в описание FSM выписываются запросы, с которыми работает обработчик состояний. Внутри блока задают значения параметров, доступных для конфигурации.
Структура описания запроса
{Request "name" {priority N} {interrupt} {duration N} {exit "state_name"} }
Request
Имя запроса. FSM выбирает состояние, у которого тег совпадает с указанным именем.
priority
Определяет приоритет запроса. При обработке конкурирующих запросов выбирается запрос с более высоким значением.
interrupt
Разрешает немедленный переход в новое состояние, принудительно завершая текущее, независимо от состояния активных анимаций. Опционально
duration
Задает максимальный интервал в тактах между последовательными вызовами запроса из кода; если запрос не вызывается в течение указанного времени, он автоматически отменяется. Опционально, только для Job-запросов
exit
Задает имя состояния для автоматического перехода при отмене запроса после превышения времени ожидания, указанного в параметре duration
.
Опционально, только для Job-запросов
Начальное состояние
Блок параметра Start
используется для указания имени состояния для инициализации юнита.
Формат описания начального fsm-состояния
{Start "state_name"}
Список состояний
С помощью блоков параметра state
задаются узлы графа FSM.
Вложенные блоки используются для описания доступных переходов между состояниями, тегов состояний и других параметров.
Структура описания параметров fsm-состояний
{State "state_name" {from "source_state"} {fromTagged "source_tag"} {transit "transit_state"} {to "target_state"} {tag "name"} {condition "name"} {split "part1" "part2"} }
State "state_name"
Уникальный идентификатор описываемого состояния
from "source_state"
Определяет исходное состояние, из которого разрешён переход в описываемое состояние.
fromTagged "source_state"
Разрешает переход в описываемое состояние из любого состояния, имеющего указанный тег.
transit "transit_state"
(Опционально) Определяет автоматический переход в следующее состояние без внешнего запроса, как только это станет возможно.
to "target_state"
Доступность перехода в указанное состояние из описываемого. Может быть указано несколько строк с параметром to
, если допустимы переходы в альтернативные состояния.
tag "name"
Тег описываемого состояния. Опционально может быть записано несколько строк с параметром tag для одного состояния.
condition "name"
Условие, при котором разрешён вход в это состояние, в качестве значения параметра указывается имя запроса.
split "part1" "part2"
Разделение объекта на полунезависимые части (например, "walk_all" "linked"). Используется для сложных переходов или действий, когда анимацию юнита можно разделить на анимации его частей: например, верхней и нижней частей туловища.
Подмножество состояний
С помощью блока параметра subset
описываются подмножества состояний, чтобы ограничить список допустимых для выбора состояний в зависимости от текущего FSM-состояния.
Структура описания FSM-подмножества
{subset "name" from "source_subset" {disable "state_A"} {enable "state_B"} }
subset
Имя fsm-подмножества. Определяет набор разрешенных и запрещенных состояний для данного поднабора.
from
Имя родительского подмножества, от которого наследуются разрешённые состояния. (Опционально)
disable
Отключает доступ к состояниям, помеченным указанным тегом, в рамках данного подмножества. Может использоваться несколько раз для разных тегов.
enable
Включает доступ к состояниям, помеченным указанным тегом, в рамках данного подмножества. Может использоваться несколько раз для разных тегов.
Last updated