Action Context

v1.0

ActionContext is the execution environment for every Action.

It’s automatically prepared by the ActionExecutor when Actions run, and shared across all Actions in a single run.

You can think of it as the “backpack” that each Action carries — filled with references to time, randomness, shared data, and services.


🔍 Key Responsibilities

Purpose
Description

Clock Access

Provides an IClock interface for time, deltaTime, and delays (usually ActionSystemClock.Instance).

Blackboard Sharing

Holds a shared Blackboard instance so restarts and RunKeys propagate to all in-flight Actions.

Deterministic Random

Supplies a seeded IRandom for reproducible random behavior across runs.

Dependency Access

Optionally holds an IServiceLocator so custom Actions can resolve services cleanly.

Custom Data

A small per-run dictionary (customData) for storing and retrieving runtime variables.

Run-Key Tracking

Provides a RunKey accessor to detect when the executor restarts (used for safe cancellation).


🧠 Lifecycle Overview

1

Prepare ActionContext

The ActionExecutor creates an ActionContext that will be shared across the run.

2

Attach shared Blackboard

The shared Blackboard is attached so all Actions reference the same storage and run-state.

3

Set RunKey / flags

The executor sets run-key and associated flags in the Blackboard for restart detection.

4

Pass context into Action.Execute()

The context is passed to each Action when executing.

5

Action reads context

Actions read Clock, RNG, Blackboard, Services, customData, etc., from the context.

6

Restart handling

When a restart occurs the Blackboard remains shared but the RunKey changes.

7

In-flight Actions stop cleanly

Actions detect the run-key change and stop gracefully to avoid “zombie” actions.


🔁 Shared Blackboard & RunKey Propagation

All Actions in a single run share the same Blackboard. When the ActionExecutor restarts:

  • It increments a RunKey in the Blackboard.

  • All existing Actions (which reference that Blackboard) detect the change.

  • They gracefully stop via their per-frame run-key check.

This prevents “zombie” Actions from continuing after a restart.

Pro Tip: This is why CloneSharingBlackboard() exists — it lets subsystems duplicate a context but keep the same Blackboard so restart signals stay unified.


⚙️ Structure Summary

public class ActionContext
{
    // Source / Game Info
    public Vector2Int gridPosition;
    public Component sourceComponent;
    public GameObject sourceGameObject;
    public int currentLevel;
    public float timeScale;
    public MonoBehaviour gameManager;

    // Custom per-run data
    public Dictionary<string, object> customData;

    // Services
    public IClock Clock;
    public IRandom rng;
    public IServiceLocator Services;
    public Blackboard Blackboard;

    // Shared Blackboard linking
    internal void AttachBlackboard(Blackboard shared);

    // Optional cloning utility
    public ActionContext CloneSharingBlackboard();
}

🧩 CloneSharingBlackboard()

Used internally by the system when an Action needs a new context object (but must retain access to the same Blackboard, services, and run-state).

Example:

var subContext = context.CloneSharingBlackboard();
subContext.SetData("SpawnIndex", 4);

This ensures restart flags, run-keys, and other runtime data remain consistent.


🪄 Custom Data Utilities

You can safely use these if you need to store runtime data:

context.SetData("Target", enemy);
Enemy e = context.GetData<Enemy>("Target");

This is particularly useful for advanced Actions or sequences that coordinate temporary data between child Actions.


🧭 Relation to Other Systems

System
Relationship

ActionExecutor

Creates and reuses the ActionContext. Attaches shared Blackboard and sets the run-key.

ActionSystemClock

Usually injected into the context for consistent timing.

Blackboard

Shared storage for restart control, typed data, and inter-Action communication.

IServiceLocator

Optional dependency provider for advanced integrations.


🧑‍💻 When to use it directly

You might interact with ActionContext directly if:

  • You’re building a custom Executor or specialized sequencing tool.

  • You need to inject your own Clock, Blackboard, or ServiceLocator.

  • You’re creating parallel or nested Actions that need their own data scope but the same restart propagation.

Otherwise, all of this happens automatically.

Last updated

Was this helpful?