Inspiaaa / UnityHFSM

A simple yet powerful class-based hierarchical finite state machine for Unity
MIT License
1.14k stars 125 forks source link

Use enums instead of strings for states #17

Closed wilg closed 2 years ago

wilg commented 2 years ago

I see that the state machine is generic, but I would like to have my states identified by enums instead of strings. However, this does not work in a hierarchical setup if the child state machines have a different enum type (which is highly desirable).

kamike commented 2 years ago

new StateMachine() PlayerState is enum

Inspiaaa commented 2 years ago

This feature is currently fully supported by UnityHFSM but not documented yet.

Every nested state machine can use its own type for the state identifiers. The only thing that all state machines in a given hierarchy have to share, is the type for the triggers / events, so that they can be passed down the hierarchy.

The StateMachine class takes 3 generic type parameters: TOwnId, TStateId and TEvent. TStateId is the type for the state names in a state machine, i.e. of its child states. If you use a state machine as a state (-> it would be a nested state machine), it itself needs an identifier for the parent state machine. This is the TOwnId type parameter. Lastly TEvent is the type for the triggers and events.

There are also multiple overloads for the StateMachine class that reduce the boilerplate code needed to get started:

Here's a small example that shows how you can mix different types:

enum PlayerStates {
    IDLE, MOVE, JUMP
}

enum MoveStates {
    WALK, DASH
}

enum Events {
    ON_DAMAGE, ON_WIN
}
var fsm = new StateMachine<PlayerStates, Events>();
var moveFsm = new StateMachine<PlayerStates, MoveStates, Events>();
var idleFsm = new StateMachine<PlayerStates, string, Events>();

fsm.AddState(PlayerStates.IDLE, idleFsm);
fsm.AddState(PlayerStates.MOVE, moveFsm);
fsm.AddState(PlayerStates.JUMP, new State<PlayerStates, Events>());
// Or simply using shortcut methods: fsm.AddState(PlayerStates.JUMP);

moveFsm.AddState(MoveStates.WALK);
moveFsm.AddState(MoveStates.DASH);
moveFsm.AddTransition(new Transition<MoveStates>(MoveStates.WALK, MoveStates.DASH));
// Or simply: fsm.AddTransition(MoveStates.WALK, MoveStates.DASH);

idleFsm.AddState("Animation 1", new State<string, Events>());
idleFsm.AddState("Animation 2");

// ...

Does this solve your problem?

wilg commented 2 years ago

Yes, perfect! I wasn't able to figure out what the other type parameters were and I think the overloads confused me. But got it working with this example! Might be useful to pop this into the docs.

Had another quick question #15 if you have a minute I would really appreciate it!