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.
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.
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”.