using XFG.AI.FSM;The IStateMachine module provides the foundational finite state machine used throughout the XFG AI framework. It is intentionally minimal, predictable, and type-safe. All advanced behavior (async transitions, hierarchical FSM, pushdown stacks) is implemented as optional extension layers.
This document describes the architecture, design goals, and usage patterns for the FSM.
For Serializable FSM support, see:
Serializable State Machine - ReadMe
For async support, see:
Async StateMachine - ReadMe
For Hierarchical FSM support, see:
HFSM - ReadMe
For Pushdown FSM support, see:
Pushdown State Machine - ReadMe
The machine uses three generic type parameters:
TMachineType- The MonoBehaviour that owns the machineTStateIDType- The identifier for states (usually an enum)TMessageType- The identifier for messages (usually an enum)
This ensures compile-time safety and eliminates string-based errors.
States implement the nested IState interface and may override:
OnStateEnterOnStateUpdateOnStateExitOnReceiveMessage
All callbacks are optional. The machine guarantees ordered transitions:
- Exit old state
- Update machine references
- Enter new state
The FSM does not:
- Auto-transition
- Implicitly update states
- Implicitly handle messages
- Modify state order
All behavior is explicit and controlled by the user.
The base FSM is intentionally minimal.
Additional capabilities are provided through optional extension layers:
- AsyncStateMachine → asynchronous transitions
- HierarchicalStateMachine → parent/child state trees
- PushdownStateMachine → stack-based state control
Each extension has its own README.
IStateMachine<TMachine, TStateID, TMessage>
- Registers states
- Stores active state
- Performs synchronous transitions
- Forwards update ticks
- Routes messages to active state
IState (nested interface)
- Machine reference
- State ID
- Enter / Update / Exit / Message callbacks
The machine does not assume a default state.
Transitions must be explicitly triggered.
public class IdleState :
IStateMachine<PlayerMachine, PlayerStateID, PlayerMessage>.IState
{
public PlayerMachine Machine { get; set; }
public PlayerStateID ID => PlayerStateID.Idle;
public void OnStateEnter(PlayerStateID prev, object[] args)
{
Machine.PlayAnimation("Idle");
}
public void OnStateUpdate()
{
if (Machine.Input.Move)
Machine.ChangeState(PlayerStateID.Move);
}
}public class PlayerMachine :
IStateMachine<PlayerMachine, PlayerStateID, PlayerMessage>
{
void Start()
{
RegisterState(new IdleState());
RegisterState(new MoveState());
RegisterState(new AttackState());
ChangeState(PlayerStateID.Idle);
}
void Update()
{
UpdateMachine();
}
}machine.SendMessageToMachine(PlayerMessage.Hit, damageAmount);States may override OnReceiveMessage to handle them.
The FSM is intentionally small. No hidden transitions, no implicit behavior.
Async and hierarchical behavior are optional layers, not built-in.
The API surface is minimal and stable.
The machine enforces ordered transitions and predictable state ownership.
Use this module when you need:
- Clean gameplay state logic
- Predictable transitions
- Strong typing
- Minimal overhead
- A stable foundation for more advanced systems
If you need async transitions or hierarchical behavior, simply add the corresponding extension layers.