Execution Engines
Categories:
gs_graphcanvas provides three execution engines — one for each topology. All share a common GraphExecutionContext for variable storage and value resolution, and GraphInstance for creating independent runtime copies.
FlowGraphEvaluator

Topology: FlowGraph
Step/wait/resume execution model for sequential graphs. The evaluator follows FlowIn/FlowOut connections from node to node.
Nodes implement the IExecutableNode interface:
FlowResult Execute(GraphExecutionContext& context);
FlowResult controls what happens after a node executes:
| Result | Behavior |
|---|---|
Continue | Immediately proceed to the next connected node |
Wait | Pause execution until Resume() is called externally |
Stop | End graph execution |
Used by: Dialogue Editor — text nodes return Wait while dialogue is displayed, then Resume() advances to the next node.
DataFlowGraphEvaluator

Topology: DataFlowGraph
Dirty-propagation evaluator for continuously-evaluated graphs. On initialization, builds a topological ordering of all nodes via Kahn’s algorithm.
Nodes implement the IDataFlowNode interface:
void Process(GraphExecutionContext& context);
Evaluation Pipeline
- Initialize — Build topological order from the graph’s connection structure
- Track dependencies — Map which nodes depend on which variables
- Mark dirty —
MarkDirty(variableName)marks dependent nodes dirty, then transitively marks all downstream nodes - Evaluate — Iterate nodes in topological order, re-running only dirty nodes
The explicit dirty marking (not automatic) gives downstream code batching control — set multiple variables, then call Evaluate() once.
Empty Any Pattern
When a data-flow node has no valid output (gated off, no valid input), it must output AZStd::any{} (truly empty), never a default-constructed value:
if (validInput)
context.SetOutputValue(this, "result", computedValue);
else
context.SetOutputValueAny(this, "result", AZStd::any{});
This is critical because multi-input resolution returns the first non-empty AZStd::any. A default-constructed struct inside an any is non-empty and will mask valid values from other connections.
Used by: Audio Event Graph — entry gate nodes, filter nodes, and effect nodes all follow this pattern.
StateMachineEvaluator

Topology: StateMachineGraph
Tick-based evaluator for hierarchical finite state machines. Maintains the current active state and evaluates transitions each tick.
Nodes implement the IStateMachineNode interface:
void OnEnter(GraphExecutionContext& context);
void OnTick(GraphExecutionContext& context, float deltaTime);
void OnExit(GraphExecutionContext& context);
Tick Cycle
- Increment
__stateTimeauto-variable - Gather all outgoing transitions from the current state
- Evaluate conditions on each transition
- Fire the highest-priority valid transition (
OnExiton source,OnEnteron destination) - Call
OnTickon the active state
Transition Conditions
Each connection carries a TransitionDescriptor with a priority and a list of polymorphic TransitionCondition objects. Built-in conditions:
| Condition | Description |
|---|---|
VariableCompareCondition | Compares a variable to a value using a comparison operator |
TimeElapsedCondition | Fires after N seconds in the current state (reads __stateTime) |
VariableTrueCondition | Fires when a boolean variable is true |
Custom conditions are created by subclassing TransitionCondition, reflecting it, and it auto-discovers via SerializeContext::EnumerateDerived().
ParallelLayerEvaluator
Wraps multiple StateMachineEvaluator instances (one per layer) with shared context synchronization. Each layer evaluates independently but shares the same variable context for cross-layer reads.
Used by: Unit Action Graph — parallel Movement, Action, and Rotation layers.
GraphExecutionContext
Shared context for all evaluator types. Provides:
- Input value resolution —
GetInputValue<T>()andGetInputValueAny()with multi-input resolution (returns first non-empty value) - Output values —
SetOutputValue()andSetOutputValueAny() - Blackboard — Variable storage by name
- Binding initialization —
InitializeBindings()resolves VariableId references to variable names
GraphInstance
An independent runtime copy of a graph. GraphInstance::CreateFromAsset() deserializes a fresh graph from a GraphDocumentAsset’s byte buffer, initializes variables and bindings. Each instance is fully independent — downstream gems can pool instances for high-frequency execution paths.