0.4 – Hierarchy FSM Architecture

0.4.0 – The design

After decades and decades, FSM is still widely used in games for behavior selection. So it makes sense to actually build one for UE4. The general idea is to run FSM from each actor, share knowledge through a customized Blackboard, and encapsulate State and Transition so that they can be re-used and even shared between different FSM.

0.4.1 – First iteration: FSM

State.h:

virtual void onEnter() = 0;
virtual void onUpdate(const float _deltaTime, Blackboard* _blackboard) = 0;
virtual void onExit(Blackboard* _blackboard) = 0;

Transition.h

virtual bool isValid(const Blackboard* _blackboard) const = 0;
virtual void onTransition() = 0;

StateMachine.h

virtual void setTransitionMap(const TransitionMap& _transitions, State* _initState);
virtual void update(const float _deltaTime, Blackboard* _blackboard);
virtual void setState(State* _state);

I also created a loader class to load a XML file and build the state machine in run-time. The XML file is like:

<fsm name="FSM_Test_1">
    <state name="Patrol" initial="1">
        <transition input="EnemySpotted" name="Combat"/>
    </state>
    ...
</fsm>

0.4.2 – Second iteration: Hierarchy

MetaState.h

class MetaState : public State, public StateMachine
...
void onUpdate(const float _deltaTime, const Blackboard* _blackboard);
virtual void setTransitionMap(const TransitionMap& _transitions, State* _initState);

Now a state can also be a state machine. But how about transitions? Transition to the upper level is different from transition to the same level, or to a lower level. So in the data file, each transition is given a level based on its from and to. Now the data file is like:

<fsm name="FSM_Test_1">
    <state name="Patrol" initial="1">
        <transition input="EnemySpotted" name="Combat" level="0"/>
    </state>
    <state name="Combat" meta="1">
        <transition input="EnemyLost" name="Search" level="0"/>
        <state name="Alert" initial="1">
            <transition input="Timeout" name="Attack" level="0"/>
        </state>
        <state name="Attack">
            <transition input="Timeout" name="Search" level="1"/>
        </state>
    </state>
    <state name="Search">
        <transition input="EnemySpotted" name="Combat" level="0"/>
    </state>
</fsm>

StateMachine.h

typedef struct
{
Transition* transition = nullptr;
State* state = nullptr;
int level = 0;
StateMachine* stateMachine = nullptr;
} UpdateResult;
virtual void onUpdate(const float _deltaTime, Blackboard* _blackboard);
virtual UpdateResult update(const float _deltaTime, Blackboard* _blackboard);
void updateDown(State* state, int level, Blackboard* _blackboard);

You May Also Like

Leave a Reply

Your email address will not be published. Required fields are marked *

The AI Project