Описание 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.
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 используется для регистрации запросов.
Каждый блок соответствует одному именованному запросу и включает параметры, определяющие правила его обработки внутри 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