Appendix
Table of Contents
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:
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.
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 thestate_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 thestate_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 thestate_exited
signal on C2 and thestate_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 thestate_entered
signal on C4.
Then we have reached this state:
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 thestate_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 thestate_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.
You can also modify this example and explore the order of events yourself.