About Hierarchical Final State Machine

HFSM (Hierarchical Finite State Machine) is a simple and flexible library for building state machines in C#. The library provides an easy-to-use API for defining states, transitions, and hierarchical relationships between states.

Feature

- Define states with custom behavior (OnEnter, OnUpdate, OnExit)

- Define transitions based on events and/or guard conditions


- Hierarchical state organization


- State machine builder for easy construction and configuration


- Event-driven state updates

Exemple of usage - Fictionnal

// Define your state and event enums

public enum MyState { Root, Idle, Walk, Run }
public enum MyEvent { FreezePlayer , StartRun}

private HFSM<MyState, MyEvent> m_hfsm;

private void BuildHFSM()
{
// Create a new HFSMBuilder instance
var builder = new HFSMBuilder<MyState, MyEvent>();

// Add states to the builder
builder.AddState(MyState.Movement);
builder.AddState(MyState.Idle, MyState.Movement);
builder.AddState(MyState.Walk, MyState.Movement, OnStartWalk, OnUpdateWalk, OnExitWalk);
builder.AddState(MyState.Run, MyState.Movement);
builder.AddState(MyState.Freeze, OnEnterFreeze);

//// Define transitions between states
// Can use a guard
builder.AddTransition(MyState.Idle, MyState.Walk, () => IsMoving);

// An event
builder.AddTransition(MyState.Movement, MyState.Freeze, MyEvent.FreezePlayer);

// Or both
builder.AddTransition(MyState.Walk, MyState.Run, () => Pawn.Velocity > 15, MyEvent.StartRun);

// Build the state machine
var hfsm = builder.Build();

}

protected override void OnActivate()
{
BuildHFSM();
base.OnActivate();
}

[GameEvent.Tick]
private void OnUpdate()
{
// Update the state machine
m_hfsm.Update();
}

private void OnStartWalk()
{
Log.Info("I'm walking!")
}

private void OnUpdateWalk()
{
// Do stuff
}

private void OnExitWalk()
{
// Do stuff
}

private void OnEnterFreeze()
{
Log.Info("It's getting cold in there!")
}

protected override void OnDeactivate()
{
// Stop the state machine
m_hfsm.Stop();
}


Another exemple - Movement controller

public partial class MovementsController : EntityComponent<Pawn>

{
private void BuildHFSM()
{
HFSMBuilder<States, TransitionEvents> builder = new HFSMBuilder<States, TransitionEvents>();
builder.AddState( States.OnGroundState , OnEnterGroundState, OnUpdateGroundState, OnExitGroundState);
{
builder.AddState( States.JogState ,States.OnGroundState, OnEnterJogState);
{
builder.AddTransition( States.JogState, States.RunState , () => Input.Down( "run" ));
builder.AddTransition( States.JogState, States.WalkState , () => Input.Down( "walk" ));
builder.AddTransition( States.JogState, States.DuckState , () => Input.Down( "duck" ));
}
builder.AddState( States.RunState ,States.OnGroundState, OnEnterSprintState);
{
builder.AddTransition( States.RunState, States.JogState , () => !Input.Down( "run" ));
builder.AddTransition( States.RunState, States.WalkState , () => Input.Down( "walk" ));
builder.AddTransition( States.RunState, States.DuckState , () => Input.Down( "duck" ));
}
builder.AddState( States.WalkState ,States.OnGroundState, OnEnterWalkState);
{
builder.AddTransition( States.WalkState, States.JogState , () => !Input.Down( "walk" ));
builder.AddTransition( States.WalkState, States.DuckState , () => Input.Down( "duck" ));
}
builder.AddState( States.DuckState, States.OnGroundState, OnEnterDuckState, null , OnExitDuckState);
{
builder.AddTransition( States.DuckState, States.JogState , () => !Input.Down( "duck" ) && CanUnduck());
}
builder.AddTransition( States.OnGroundState, States.InAirState , () => !Grounded);
}
builder.AddState( States.InAirState , OnEnterAirState, OnUpdateAirState, OnExitAirState);
{
builder.AddTransition( States.InAirState, States.DuckState , () => Input.Down( "duck" ) && Grounded );
builder.AddTransition( States.InAirState, States.OnGroundState , () => Grounded );
}
m_hfsm = builder.Build();
}
}
}