# Lifecycle and Dataflow

Level: Intermediate

## Goal

Explain runtime order, entry points, and how data is resolved.

## Route notes

* Read [Value Sources and Target Resolution](/flow-core-docs/documentation/runtime-guide/value-sources-and-target-resolution.md) when choosing between Blackboard, payload, TempPayload, context shortcuts, GameObjectGuid tags, and target resolver paths.
* Read [Stack Runtime Model](/flow-core-docs/documentation/runtime-guide/stack-runtime.md) when a graph uses Stack Root and Stack Layer lifecycle outputs instead of a single linear chain.
* Read [TempPayload](/flow-core-docs/documentation/runtime-guide/temp-payload.md) when chain-local scratch data is passed between instructions or target resolver steps.

## Initialization order (what runs first)

1. FlowCoreSettingsBootstrap applies FlowCoreSettings before scene load.
2. FlowRegistryBootstrap registers generated registries.
3. FlowCoreProcess.Awake builds blackboards and FlowGraphRuntime.

## Runtime entry points

* FlowCoreProcess.PublishUnityTrigger: start chains from events.
* FlowCoreProcess.ExecuteEnter: start chains by Entry name or index.
* FlowEventBus: publish Global/Local events by FlowEventKey.

Example: publish a global event trigger with payload.

```csharp
using TwoCatsCode.FlowCore;

public static class CombatSignals
{
    private static readonly FlowEventKey StartKey = new FlowEventKey("Combat.Start");

    public static void PublishStart()
    {
        FlowEventBus.Global.Publish(StartKey, new FlowTriggerPayload(1), FlowSignalContext.None);
    }
}
```

## SignalContext payload (Enter)

* FlowSignalContext can carry optional payload for ExecuteEnter/ExecuteEnterByTitle.
* When payload is not provided, Enter starts with empty payload, IndexPayload = 0, TriggerOutputIndex = -1.
* Triggers still use FlowTriggerPayload parameters; SignalContext payload does not replace trigger payload.

## SignalContext payload (Event Bus)

* FlowEventBus.Publish has an overload that accepts FlowSignalContext.
* If signalContext.HasPayload is true, that payload is used for the trigger; otherwise it defaults to None.

## Event Bus publish semantics (important)

* Publish snapshots the current handler list before invocation.
* Unregister/Register during Publish does not affect the current dispatch; it only applies to the next Publish.
* Best practice: if a handler needs to unregister itself or destroy a GameObject, defer by 1 frame to reduce re-entrancy and lifetime hazards.
* FlowEventBus is not thread-safe; publish from the main thread.

## Behavior Tree runtime model

* BTRoot is the only entry into a BT branch. It can be reached from Flow and returns to Flow via Success/Failure outputs.
* BTRoot owns the BT tick loop and stays active while the tree runs.
* Child order is left-to-right execution priority.
* Composite modes:
  * Reactive: re-evaluates from the first child every tick (priority can preempt).
  * Memory: continues from the last running child until it finishes.
* Parallel strategy is configurable (Any / All / AllComplete).
* BTAction runs its instruction list; any non-Continue result ends the node and returns Success.
* BTLoop mirrors Flow Loop semantics but is BT-only.
* BtSubGraph runs a referenced graph from a selected BTRoot and maps results by Return Mode.
* Guard on BTRoot is checked continuously; Guard failure returns Invalid/Abort and cancels the BT branch.
* Guard on BT leaf nodes maps Reject Result: Invalid → Success, Abort → Abort.

## FSM State runtime sequencing

* Scope: `Execution Policy` matching only applies inside one `FlowGraphRuntimeData`.
* Entry path: Guard is evaluated first. If the policy is `Exclusive`, the runtime requests cancel on other active `FsmState` nodes in the same `FSM Group ID`. The entering state then registers itself and runs its own `Enter`.
* Direct transition path: when state A selects a transition to state B, A runs `Exit` and that `Exit` is awaited before the main execution loop continues to B. Direct transitions are serialized, not overlapped.
* Exclusive preemption path: a preempted state receives a cancel request, consumes it on its own FSM loop or wait boundary, runs `Exit`, and then stops. The entering `Exclusive` state does not wait for that `Exit` to finish before continuing its own `Enter`.
* Instruction mode and Graph mode both preserve this serialized direct-transition handoff. Graph mode still awaits the exit-side graph entry before continuing to the next state.
* `Parallel` changes only the entry-time preemption rule. It does not create overlap between `A.Exit` and `B.Enter` on one direct transition edge.
* Concurrency exists only between independently active FSM states that are already running. It does not apply to the handoff on a single direct transition edge.

## Control inputs and Pass Enabled gate

* Flow nodes with control inputs maintain a **Pass Enabled** gate (default on).
* **Enable/Disable** control inputs toggle this gate without changing the node **Enabled** flag.
* When Pass Enabled is off, incoming chains return **Invalid** and the node does not execute.
* On BTRoot, **Disable** only toggles Pass Enabled; it does not interrupt a running BT branch.
* Nodes without control inputs ignore Pass Enabled.

## Runtime rebuild APIs (when to use)

* RebuildRuntime: after swapping GraphAsset at runtime (aborts chains).
* RebuildBlackboards: after changing blackboard lists (does not abort chains).

## Runtime blackboard list mutation (safe pattern)

1. Apply list changes with rebuild=false.
2. Call RebuildBlackboards once.
3. Expect new lists to resolve on next access.

```csharp
process.AddLocalBlackboard(localA, rebuild: false);
process.InsertLocalBlackboard(0, localB, rebuild: false);
process.RebuildBlackboards();
```

## Set List semantics

* `Set List *` instructions still execute when both `Replace` and `Append` are off.
* Default state (`Replace = false`, `Append = false`) keeps the current list instance, clears its contents, then writes the incoming values.
* `Append = true` keeps the current list instance and appends the incoming values to the end.
* `Replace = true` creates a new list instance, writes it back to the destination key, then fills that new list with the incoming values.
* `Replace` and `Append` are not strict opposites. `Replace` controls whether the list instance itself is replaced; `Append` controls whether existing contents are preserved.
* When `Replace = true`, `Append` has no meaningful extra effect because the new list starts empty. The current UI hides `Append` in that state to avoid exposing a toggle that does not materially change the result.

## Blackboard reference fallback (runtime)

* If **LocalBlackboard\[0]** is missing, FlowCoreProcess tries to use a `Blackboard` on the same GameObject and assigns it to index 0.
* If **SceneBlackboard\[0]** is missing, FlowCoreProcess tries to use the `SceneBlackboard` in the active scene and assigns it to index 0.
* Multiple SceneBlackboard instances are allowed; use explicit references for deterministic selection.

## Subgraph activation window

* SubFlowGraph executes sub-graph chains using caller context.
* Triggers inside sub-graphs only run within the activation window.
* Lifecycle events are not replayed when sub-graphs become active.

## Dataflow contracts

* FlowValueGet/FlowValueSet resolve from process-bound Blackboard paths, payload, TempPayload, literal data, or Target resolver paths.
* Target resolution uses resolver steps, not string paths.
* FlowContext refreshes caches when blackboard versions change.
* Payload is provided by the entry point that starts the chain. TempPayload is written during the chain and is cleared when that chain ends.

## Performance note (important)

* Changing list lengths frequently forces FlowContext cache rebuilds.
* Batch changes to avoid GC spikes.

## Edit mode preview

* FlowCoreProcess can build a preview FlowContext for Summary.
* Debug Context determines which blackboards are used.

## Visual Debugging (Editor-only)

* Runtime records node transitions plus per-entry instruction/condition results.
* Async waits create hold records; the editor renders them as pulsing highlights.
* Debug events are per-process and filtered by Debug Context.
* Visual Debugging is compiled out in player builds.

## Related

* [Runtime Integration](/flow-core-docs/documentation/tutorials/run-a-flow-graph-in-a-scene.md)
* [Value Sources and Target Resolution](/flow-core-docs/documentation/runtime-guide/value-sources-and-target-resolution.md)
* [Stack Runtime Model](/flow-core-docs/documentation/runtime-guide/stack-runtime.md)
* [TempPayload](/flow-core-docs/documentation/runtime-guide/temp-payload.md)
* [Invoke and Reject Modes](/flow-core-docs/documentation/reference/invoke-and-reject-modes.md)
* [Persistence](/flow-core-docs/documentation/api-extension-guide/persistence.md)


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://flow-core.gitbook.io/flow-core-docs/documentation/runtime-guide/lifecycle-and-dataflow.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
