Appendix

Index

Order of events

Usually you don’t need to worry too much about the order in which state changes are processed but there are some instances where it is important to know the order in which events are processed. The following will give you an overview on the inner workings and the order in which events are processed.

Generic event handling rules

The state chart reacts to these events:

  • an explicit event was sent to the state chart node using the send_event function.
  • an expression property was changed using the set_expression_property function.

Whenever an event occurs, the state chart will try to find transitions that react to this event. Only transitions in states that are currently active will be considered. Transitions will be checked in a depth-first manner. So the innermost transition that handles any given event (be it explicit or automatic) will run. When a transition runs, the event is considered as handled and will no longer be processed by any other transition, except if that other transition happens to live in a parallel state (each parallel state can handle events even if that event was already handled by another parallel state). If the transition has a guard and it evaluates to false then the next transition that reacts to the event will be checked. If no transition reacts to the event, the event will bubble up to the parent state. This process will continue until the event is handled or the root state is reached. If the event is not handled by any state, it will be ignored.

Example

For this example we will use the following state chart:

Example state chart for the order of events

When the program starts, state B is active. Since it is a parallel state, it will automatically activate its child states, B1 and B2. This is the starting position.

The starting position

Now we send an event to the state chart that will trigger a transition to state C. Now the following things will happen:

  • Since we leave B, the child states B1 and B2 will exited. They are exited in the order in which they are defined, so first B1 and then B2. This will also emit the state_exited signal on each of the child states.
  • Then B will exit and emit the state_exited signal.
  • Now we enter C which is a compound state. First the state_entered signal will be emitted on C. Now C will look for its initial state which is C1 and will activate it. This will emit the state_entered signal on C1.
  • We can see that C1 has a transition named Immediately to C2 which will immediately transition the active state from C1 to C2. This will emit the state_exited signal on C1 and the state_entered signal on C2.
  • On C2 we have another little contraption, a receiver on C2’s state_entered signal. This will send an event to the state chart which triggers the To C3 transition. So we will immediately transition from C2 to C3. This will emit the state_exited signal on C2 and the state_entered signal on C3.
  • Until here, everything happens within the same frame. On C3 we have a delayed transition to C4 which is executed 0.5 seconds later. This will emit the state_exited signal on C3 and the state_entered signal on C4.

Then we have reached this state:

The end position

Now we can switch back to state B by sending the appropriate event to the state chart. This will trigger the following events:

  • Since we leave C, the currently active state C4 will be exited and the state_exited signal will be emitted for this state. Then C will be exited and the state_exited signal will be emitted for this state.
  • We now enter B again, and fire the state_entered signal on B. Since B is a parallel state, it will activate its child states B1 and B2 again. This will emit the state_entered signal on B1 and B2.

You can also see this in action in the order_of_events example in the godot_state_charts_examples folder. The History tab of the state chart debugger will show you the order in which the events are processed.

History debugger in action

You can also modify this example and explore the order of events yourself.