Finite State Machine (FSM)
The Finite State Machine (FSM) system provides centralized management of game object states in Gem RTS. It processes incoming state change requests from various control subsystems — such as AI, user commands, physics, and others — and ensures valid and consistent state transitions.
The primary purpose of the FSM is to resolve conflicts between multiple requests and select the most appropriate state for the object. This maintains logical consistency, smooth animation transitions, and correct operation of gameplay mechanics.
FSM Functions
Receive state change requests from external control systems.
Resolves conflicts between incoming requests.
.Selects valid state transitions based on current state and conditions
Update and broadcast the current state to dependent systems, including animation, behavior, and scripting subsystems.
The finite state machine logic is defined in the unit’s .def
file using the fsm
block
FSM Components
State
A state represents the current position or action of a unit (e.g., stand
, walk
, fire
, blown_away
).
At any given moment, a unit can be in only one state.
States function as nodes in the FSM transition graph.
Each state:
has a unique name;
has at least one tag;
is connected to other states through defined transitions, forming possible state switches.
Tags
A tag is a textual label assigned to a state. Tags serve two purposes:
They allow external systems to identify the logical condition of the unit.
They define which request should trigger a transition to that state. Example: A state tagged with
fire
will be selected in response to afire
request.
Requests
A request is an external command issued by control subsystems (AI, user input, physics, etc.) that initiates the process of transitioning a controlled object to a new state within the FSM.
Unlike a signal, which is an instantaneous event, a request can remain active for a period of time — until it is either processed or canceled.
Each request is associated with at least one FSM state via a tag that matches its name. The presence of this tag enables the FSM to identify which state can handle the given request, provided the transition conditions are met.
Tags in states are used not only to handle FSM requests but also by other game subsystems.
The result of request processing depends on:
the current state of the unit;
the priority of the request;
the transition rules defined in the FSM graph.
FSM supports multiple types of requests.
The table of request types is provided for reference to give a complete understanding of how the Finite State Machine (FSM) works in Gem RTS.
Request Types
Switch
A one-time request triggered in the code. It enters a queue and waits for an opportunity to execute. Once executed, it is removed.
Command: “Go prone”
Job
This request type is called every tick by the code after the unit transitions into the target FSM state. It holds the unit in that state as long as the request remains active.
The request is reset if it is not called for longer than the duration
parameter or if a higher-priority request is received.
When reset, it triggers a Switch request from the exit
block in the FSM description, if the unit is still in the target state.
Command: “Repair”
Action
This request is triggered every tick before the unit is allowed to enter the target state. If conditions are met, it transitions the unit into the state to perform the action, and then it is removed. If not triggered for at least one tick, it is discarded without execution.
Command: “Throw grenade”
State
A one-time request that causes an immediate transition into the target state. The state is maintained until it is canceled or a higher-priority request arrives.
Hide the weapon if it gets stuck in a wall
The request and tag system is used in the engine to coordinate the behavior of various gameplay subsystems. Some requests and tags are hardcoded, while others can be defined in configuration files (e.g., interface elements, inventory items, weapons), allowing developers to modify and extend object behavior without altering the source code.
State Subsets
An FSM Subset is a component of the finite state machine that defines restrictions on state transitions by excluding states that are incompatible with the unit’s current state.
Example: If a unit is holding a fuel canister, the FSM subset excludes the states prone, squat, and repair, as performing these actions would be incompatible with the unit's current condition.
Request Processing in FSM
Stages of the request processing workflow
FSM Subset Selection Based on the unit’s current state, the state handler selects an FSM subset that limits the pool of states available for transition.
Priority Analysis If multiple requests are received simultaneously, the FSM analyzes their priorities. The request with the highest priority takes precedence when selecting the next state. Requests with equal priority are resolved in the order they were received.
Transition Availability Check:
Whether the FSM graph defines a transition to the target state from the current state.
Whether the conditions are met (e.g., presence of specific tags or additional request parameters).
Request Processing Result The FSM selects the nearest available state in the graph that matches the request tag, regardless of whether it is directly connected to the current state — state transitions may pass through intermediate states.
Typical FSM Scenario Initial position: the unit is in an idle state. Combat begins: the unit detects an enemy, receives an attack command from the AI, and simultaneously a “dig in” command from the player. A nearby explosion occurs, with a blast strong enough to knock the unit back and cause damage. State change requests are sent to the FSM. Since the unit cannot be in multiple states at once (digging in, attacking, reacting to the explosion, healing, or dying), the FSM resolves this conflict by selecting the most prioritized and valid state.
When the new state is activated, the state handler passes the state to the game systems and triggers the scripts and animations associated with that state.
Upon exiting the state, the handler notifies the game systems of the state’s completion, stops the corresponding animations and effects, terminates all processes and scripts linked to the state, and then clears the used resources.
FSM Configuration Components
The logic of the finite state machine is defined in the unit’s .def
file using the fsm
block:
FSM block syntax
{fsm "name" ... }
where
"name"
is the name of the FSM.
The FSM description can be placed in a separate file or directory. For example, in the resources of the Men of War game series:
\properties\animal.ext
— FSM for thehorse
entity\properties\human_fsm\
— FSM for thehuman
entity
Request List
A complete description of requests is available in the source code. Only parameters available for configuration are exposed in the configuration file.
The request
parameter blocks are used to declare the requests handled by the state processor within the FSM description. Each block contains values for configurable parameters.
Request block syntax
{Request "name" {priority N} {interrupt} {duration N} {exit "state_name"} }
Request
Request name. The FSM selects a state whose tag matches this name.
priority
Defines the request’s priority. When processing competing requests, the one with the higher value is selected.
interrupt
Allows immediate transition to a new state, forcibly terminating the current one regardless of active animations.Optional
duration
Sets the maximum number of ticks between consecutive calls to the request from code. If the request is not called within the specified time, it is automatically canceled.Optional; applicable only to Job-type requests
exit
Specifies the name of the state to transition to automatically when the request is canceled due to a timeout as defined by the duration parameter.Optional; applicable only to Job-type requests
Initial State
The Start
parameter block is used to specify the name of the initial state for unit initialization.
Initial FSM State Definition Format
Start block syntax
{Start "state_name"}
State List
The state
parameter blocks are used to define the nodes of the FSM graph.
Nested blocks are used to describe available transitions between states, state tags, and other parameters.
State Block Syntax
{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"
Unique identifier of the defined state.
from "source_state"
Defines the source state from which a transition to this state is allowed.
fromTagged "source_tag"
Allows transition into this state from any state that has the specified tag.
transit "transit_state"
(Optional) Defines an automatic transition to the next state without an external request, as soon as conditions allow.
to "target_state"
Declares a valid transition from this state to the specified target state. Multiple to
parameters can be used for alternative transitions.
tag "name"
Tag assigned to the state. Multiple tag
entries may be specified for a single state. (Optional)
condition "name"
Condition required for entering this state. The value should match the name of a request.
split "part1" "part2"
Divides the object into semi-independent parts (e.g., "walk_all"
"linked"
). Used for complex transitions or actions when unit animation can be split into parts — for example, upper and lower body.
State names and tag values must be enclosed in double quotes.
State Subset
The subset
parameter block is used to define FSM subsets that restrict the list of valid states available for selection based on the unit’s current FSM state.
Subset block syntax
{subset "name" from "source_subset" {disable "state_A"} {enable "state_B"} }
subset
Name of the FSM subset. Defines a set of allowed and disallowed states for this subset.
from
Name of the parent subset from which allowed states are inherited.(Optional)
disable
Disables access to states tagged with the specified value within this subset. Can be used multiple times for different tags.
enable
Enables access to states tagged with the specified value within this subset. Can be used multiple times for different tags.
Last updated