Class ScyllaStateMachine<TContext>
A lightweight, allocation-free finite state machine operating on a shared context. Exactly one state is current at a time; transitions run the exit callback of the old state followed by the enter callback of the new state.
Inheritance
Inherited Members
Namespace: Scylla.Core.Structures
Assembly: ScyllaCore.dll
Syntax
public class ScyllaStateMachine<TContext>
Type Parameters
| Name | Description |
|---|---|
| TContext | The shared context type passed to every state callback. Typically a blackboard object holding the data all states of this machine operate on. |
Remarks
The machine is a plain C# class with no Unity dependency and performs no heap allocations after construction. It is driven explicitly through Tick(float) and FixedTick(float); there is no implicit update.
Transitions are guarded: TransitionTo(IScyllaState<TContext>, bool) first asks the target state's CanEnter(TContext) and keeps the current state when the guard rejects. Calling TransitionTo(IScyllaState<TContext>, bool) from inside an enter or exit callback throws InvalidOperationException; request follow-up transitions from tick callbacks instead.
Optional global transitions (see AddGlobalTransition(IScyllaTransition<TContext>)) are evaluated in priority order at the start of every Tick(float), regardless of the current state. A machine without global transitions pays a single null check per tick.
The machine is not thread-safe. Drive it from a single thread, typically the Unity main thread.
var machine = new ScyllaStateMachine<PlayerContext>(context);
machine.Start(idleState);
machine.TransitionTo(runState);
machine.Tick(Time.deltaTime);
Constructors
ScyllaStateMachine(TContext)
Creates a new state machine operating on the given context.
Declaration
public ScyllaStateMachine(TContext context)
Parameters
| Type | Name | Description |
|---|---|---|
| TContext | context | The shared context passed to every state callback. |
Properties
Context
Gets the shared context passed to every state callback.
Declaration
public TContext Context { get; }
Property Value
| Type | Description |
|---|---|
| TContext |
CurrentState
Gets the currently active state, or null while the machine is stopped.
Declaration
public IScyllaState<TContext> CurrentState { get; protected set; }
Property Value
| Type | Description |
|---|---|
| IScyllaState<TContext> |
IsRunning
Gets a value indicating whether the machine has been started and not yet stopped.
Declaration
public bool IsRunning { get; protected set; }
Property Value
| Type | Description |
|---|---|
| bool |
PreviousState
Gets the state that was current before the most recent transition, or
null if no transition has happened since Start(IScyllaState<TContext>).
Declaration
public IScyllaState<TContext> PreviousState { get; protected set; }
Property Value
| Type | Description |
|---|---|
| IScyllaState<TContext> |
Methods
AddGlobalTransition(IScyllaTransition<TContext>)
Registers a global transition that is evaluated at the start of every Tick(float), regardless of the current state. Transitions are evaluated in descending Priority order; transitions of equal priority keep their registration order. At most one global transition fires per tick.
Declaration
public void AddGlobalTransition(IScyllaTransition<TContext> transition)
Parameters
| Type | Name | Description |
|---|---|---|
| IScyllaTransition<TContext> | transition | The transition to register. |
Remarks
Evaluate(TContext) must be side-effect-free and must not call TransitionTo(IScyllaState<TContext>, bool) itself; the machine performs the transition when the condition holds.
Exceptions
| Type | Condition |
|---|---|
| ArgumentNullException | Thrown when |
BeginGuardedCallback()
Marks the start of a guarded state callback section. Transition-initiating
calls made while the section is open throw. Always pair with
EndGuardedCallback() in a finally block.
Declaration
protected void BeginGuardedCallback()
EndGuardedCallback()
Marks the end of a guarded state callback section opened by BeginGuardedCallback().
Declaration
protected void EndGuardedCallback()
EnterStateGuarded(IScyllaState<TContext>)
Runs a state's enter callback inside a guarded section, so transition attempts from within the callback throw.
Declaration
protected void EnterStateGuarded(IScyllaState<TContext> state)
Parameters
| Type | Name | Description |
|---|---|---|
| IScyllaState<TContext> | state | The state whose enter callback to run. |
ExitStateGuarded(IScyllaState<TContext>)
Runs a state's exit callback inside a guarded section, so transition attempts from within the callback throw.
Declaration
protected void ExitStateGuarded(IScyllaState<TContext> state)
Parameters
| Type | Name | Description |
|---|---|---|
| IScyllaState<TContext> | state | The state whose exit callback to run. |
FixedTick(float)
Forwards a fixed-rate tick to the current state. Global transitions are NOT evaluated here; they fire only from Tick(float). Does nothing while the machine is stopped.
Declaration
public void FixedTick(float fixedDeltaTime)
Parameters
| Type | Name | Description |
|---|---|---|
| float | fixedDeltaTime | The fixed step duration in seconds. |
RaiseStateChanged(IScyllaState<TContext>, IScyllaState<TContext>)
Raises the StateChanged event. Subclasses use this to report transitions performed through their own mechanics (for example push and pop).
Declaration
protected void RaiseStateChanged(IScyllaState<TContext> previous, IScyllaState<TContext> next)
Parameters
| Type | Name | Description |
|---|---|---|
| IScyllaState<TContext> | previous | The state that was current before the change (may be null). |
| IScyllaState<TContext> | next | The state that is current after the change (may be null). |
RemoveGlobalTransition(IScyllaTransition<TContext>)
Removes a previously registered global transition.
Declaration
public bool RemoveGlobalTransition(IScyllaTransition<TContext> transition)
Parameters
| Type | Name | Description |
|---|---|---|
| IScyllaTransition<TContext> | transition | The transition to remove. |
Returns
| Type | Description |
|---|---|
| bool |
|
Start(IScyllaState<TContext>)
Starts the machine and enters the given initial state. The initial state's
CanEnter(TContext) guard is consulted; if it
rejects, the machine does not start and false is returned.
Declaration
public bool Start(IScyllaState<TContext> initialState)
Parameters
| Type | Name | Description |
|---|---|---|
| IScyllaState<TContext> | initialState | The state to enter first. |
Returns
| Type | Description |
|---|---|
| bool |
|
Exceptions
| Type | Condition |
|---|---|
| ArgumentNullException | Thrown when |
| InvalidOperationException | Thrown when the machine is already running. |
Stop()
Stops the machine, exiting the current state. Safe to call when the machine is not running (no-op).
Declaration
public virtual void Stop()
ThrowIfTransitioning()
Throws when called from inside an enter or exit callback. Transition-initiating methods call this before mutating machine state.
Declaration
protected void ThrowIfTransitioning()
Exceptions
| Type | Condition |
|---|---|
| InvalidOperationException | Thrown when a transition is currently in progress. |
Tick(float)
Forwards a variable-rate tick to the current state, after evaluating any registered global transitions. When a global transition fires, the new current state receives the tick. Does nothing while the machine is stopped.
Declaration
public void Tick(float deltaTime)
Parameters
| Type | Name | Description |
|---|---|---|
| float | deltaTime | The elapsed time in seconds since the previous tick. |
TransitionTo(IScyllaState<TContext>, bool)
Transitions from the current state to the given state. The old state's exit
callback runs before the new state's enter callback. Transitioning to the state
that is already current is rejected unless allowReentry is
true, in which case the state exits and re-enters.
Declaration
public bool TransitionTo(IScyllaState<TContext> nextState, bool allowReentry = false)
Parameters
| Type | Name | Description |
|---|---|---|
| IScyllaState<TContext> | nextState | The state to transition to. |
| bool | allowReentry | Whether a transition to the already-current state should exit and re-enter it.
Defaults to |
Returns
| Type | Description |
|---|---|
| bool |
|
Exceptions
| Type | Condition |
|---|---|
| ArgumentNullException | Thrown when |
| InvalidOperationException | Thrown when called from inside an enter or exit callback. Request follow-up transitions from tick callbacks instead. |
Events
StateChanged
Raised after every completed transition, including the initial transition
performed by Start(IScyllaState<TContext>) (with a null previous state) and the
final transition performed by Stop() (with a null next
state). The first argument is the previous state, the second the new state.
Declaration
public event Action<IScyllaState<TContext>, IScyllaState<TContext>> StateChanged
Event Type
| Type | Description |
|---|---|
| Action<IScyllaState<TContext>, IScyllaState<TContext>> |