Submachine States

Layering FSMs the easy way

A third alternative to the state classes has been introduced in v1.5 of GC FSM. Similarly to Local States, the intent is to avoid creating separate implementation classes, with the main difference that the new state runs a sub-FSM defined in the same object as the state node.  In order to create an FSM Submachine State, right-click on the background of the event graph and select “FSM Submachine State” from the GC FSM category. You can immediately edit the name of the state.

This node is essentially equivalent to a regular State that calls a Launch FSM in its OnEnter handler. However, since the sub-FSM is defined in the same object, its implementation has direct access to the object internals, without the need to pass through the Context variable.

Please notice that is a subtle, but important, difference between a Submachine State and a Local State that launches an FSM: in the case of a Submachine State the new FSM is actually a sub-FSM that will be interrupted if the Submachine State is exited, while we saw earlier that handlers of a Local State launch FSMs at the same hierarchy level as the original FSM.

You can rename the sub-FSM at any moment and the Submachine Node will be automatically updated. If you delete the sub-FSM, the node will be invalidated.

The same sub-FSM can be referenced in multiple Submachine State nodes. However, launching an FSM while it is already running will fail and may produce unexpected results. Don’t do that!

Once an FSM Submachine State has been assigned an FSM, double clicking on the node will bring you to the sub-FSM node.

You can switch a state node from regular state node to local state node at any time, by right-clicking on the node an select the “Convert to Regular/Local State” command in the context menu

How to Create a Submachine State node
A Submachine State node

How to implement “Any State” transitions with Submachine States

Other FSM design tools introduce the concept of “Any State”, that is a pseudo state that handles events regardless of the actual state the FSM is running. That approach is powerful, but promotes poorly structured FSMs that eventually become a burden to maintain and evolve. You can usually achieve the same result by organizing your FSMs in layers and Submachine State help you keep the different layers in the same object.

In the following example we see a a very simple FSM using the “Any State” facility. It has normal three states: Idle, Move and Shoot.

An example FSM using "Any State"

The “normal” execution flow occures between the Idle and Move states. However, the presence of the “Any State” introduces an “exceptional” flow which is triggered by the user pressing the fire button: in that case the FSM exits whatever state (Idle or Move) it’s in and makes a transition to the Shoot state. When the user eventually stops firing, the FSM gets back to Idle and resumes the normal flow.

Notice that this approach doesn’t visually render the presence of the two distinct flows, especially since the one with the highest priority (the “shoot”) is not represented if it weren’t for the “Any State”.

This is how you could implement the same scenarion with a two-layer FSM in GC FSM. There’s a main FSM handling the higher priority shoot/no-shoot transition and a sub-FSM dealing with the regular movement.

A two-layer FSM implementing the same behaviour