Remember the Trigger Event node? We still have to discuss the five advanced policies that were briefly introduced in the Working with an FSM section. The policies can be used to tweak the effect of the Trigger Event node. Each policy can be specified either in the Details panel of the node or as a pin in the node itself. Moreover, at the bottom of the Trigger Event node itself, graphical icons reminds you about the different policies selected for the node.
Event management details
TriggerEvent details
This is a detailed breakdown of what happens when an event is triggered with the TriggerEvent node:
- First of all, the effective target is determined. The object attached to the “Target” pin of the TriggerEvent node is considered:
- if it’s a state object (that is, an object whose class is a subclass of “FSM State”) then the “Effective Target” policy decides wheter the effective target is the object itself or its context object.
- otherwise, the effective target is the object itself (it is assumed to be a context object)
- For each FSM of the effective target:
- The event is appended to a per-FSM queue, according to the Queue Policy:
- If the policy is “Multiple events allowed”, the event is always queued
- If the policy is “Unique event: keep first”, the event is queued only if there’s no matching event already in the queue
- If the policy is “Unique event: keep last”, all matching event already in the queue are removed, then this event is queued
- If the Trigger in Substates policy is enabled and the active state has an implementation class, then the process is performed recursively on all FSMs run by the active state
- The event is appended to a per-FSM queue, according to the Queue Policy:
Notice that the Trigger Internal Events and Expire After policies are stored in the queued event since their effect will be applied when the event is processed.
Event and tick processing
All context objects perform their event processing by registering to a specific engine tick event, more precisely the “UWorld::Tick – TickObjects” part of the world tick. Such event happens after TG_PostPhysics tick functions, but before updating the camera. For each context object, all the top-level FSMs are considered in an unspecified order. This is a detailed breakdown of the tick processing for an FSM:
- All queued events are considered, in the order of reception:
- if the event has an expiration time set by the Expire After policy and the expiration time has passed, the event is discarded
- if the event is listed as “deferred” by the active state, it’s moved in a separate list of deferred events
- if there’s a matching transition in the active state, the active state is exited and the transition is executed. This case interrupts the processing on this FSM for this tick. In particular:
- the rest of the queue is not examined: it will be re-examined by the new state, possibly on the next tick
- the C++ Tick() function and OnTick blueprint event are not called
- if there’s a matching internal event, the internal event handler is executed
- otherwise, the event is ignored
- The C++ Tick() function is called. Unless the function has been overridden in C++, this eventually calls the OnTick blueprint event on the state object (if any)
- If the correspoding state node has an attached “Tick” pin, the pin is executed
- If the state has a time out transition and the time out as expired, the state is exited and the timeout transition is executed
Notice that if an FSM has no active state on a specific tick, for example because the execution flow is stuck on a latent function, the tick processing is skipped entirely. This means that the FSM still receives and queues events, but it doesn’t process them.
Deferred event processing
When a new state is entered, a new queue is assembled by appending the queue of deferred events and the queue of unprocessed events. This new queue is then processed normally, by the new state, on the next tick.
Pausing the FSMs
Since context objects register themselves directly to the world tick, they still work and process the events even if their are run by an actor whose tick function is not running. If you need to pause the FSMs, you can use the Pause FSMs blueprint node. Notice that if you do that, all FSMs and sub-FSMs of the specified context object will be paused. Pausing means that the tick processing described in the above section will not be performed, therefore:
- Triggered events will still be received and queued, but not processed
- Execution blocked in-between two states, for example in a latent function, will not be paused
You can check whether a context object has its FSMs paused using the blueprint node Are FSMs Paused.
Running FSMs while the game is paused
If the game is paused, for example with the Set Game Paused blueprint node, all FSMs of all objects will also be paused. If you desire to have the FSMs of a specific context object to run even if the game is paused, for example in order to drive a menu system, you can use the Should FSMs Run While Game Is Paused blueprint node. As with the pause nodes described above, this will affect all FSMs of the specified context object.