Events and Runners#
Code can execute designer-authored logic through an existing Event component or a serialized Runner field. Use an Event for scene-authored behavior and a Runner to expose extension points on your own component.
The Event component#
The Event component implements the runtime and cancellation contracts used by its Instructions. Its class declaration, with the body omitted, is:
public class Event : MonoBehaviour, ICancelToken, IRunIRun starts or schedules the sequence, while ICancelToken stops it when the Event is disabled or destroyed. Choose between immediate return and awaiting completion through these members:
| Member | Does |
|---|---|
Run() |
Runs the Instructions with a default context. Fire and forget. |
Run(Args args) |
Runs them with the context you supply. |
Schedule() |
Returns the Awaitable for awaiting completion. |
Schedule(Args args) |
Same, with a supplied context. |
Stop() |
Cancels the running sequence. |
IsRunning |
Whether it's mid-sequence. |
RunningIndex |
Which Instruction is executing. |
Use Schedule(args) when the caller must wait for the sequence to finish:
Event myEvent = target.GetComponent<Event>();
using Args args = Args.Get(this.gameObject, target);
await myEvent.Schedule(args);The await waits for myEvent to finish before the caller continues. Use Run when the caller can continue immediately.
Events#
These notifications let your component observe the sequence as it runs:
| Event | Fires |
|---|---|
EventInstructionStartRunning |
When the sequence starts. |
EventInstructionEndRunning |
When it finishes or is canceled. |
EventInstructionRun |
Each time an Instruction begins, with its index. |
An Event that's already running ignores further requests to start rather than queueing them.
Host logic with Runners#
RunnerInstructions adds a designer-authored Instructions list to your component:
using UnityEngine;
using VisualScript.Runtime;
public class MyDoor : MonoBehaviour
{
[SerializeField] private RunnerInstructions m_OnOpen = new RunnerInstructions();
[SerializeField] private RunnerConditions m_CanOpen = new RunnerConditions();
public void TryOpen()
{
using Args args = Args.Get(this.gameObject, this.gameObject);
if (!this.m_CanOpen.Run(args)) return;
this.m_OnOpen.Run(args).Fire(null, this);
}
}The Inspector shows Instructions and Conditions lists on MyDoor. When TryOpen runs, m_CanOpen checks whether opening is allowed; if it returns true, m_OnOpen runs the configured response.
Runner fields keep host components configurable
A hard-coded door has one response. A door with RunnerInstructions can run a sound, camera shake, or quest update without changing MyDoor.
Add a runner at the moments where designers need to attach project-specific behavior.
Running#
The Instructions runner offers overloads for cancellation and instance reuse:
| Method | Does |
|---|---|
Run(args) |
Runs the Instructions, returning an Awaitable. |
Run(args, cancelToken) |
Same, with an explicit cancellation token. |
Run(args, poolId) |
Same, reusing a pooled runner instance. |
RunnerConditions.Run(args) returns a bool and is synchronous. An empty Conditions list returns true.
Pooling runners#
Each execution needs a runner instance. The plain overload creates one, while the pool overload reuses an instance. Add a shared pool ID to MyDoor:
private static readonly IdString POOL_ID = new IdString("my-door");Then pass it to Run inside TryOpen:
this.m_OnOpen.Run(args, POOL_ID).Fire(null, this);POOL_ID groups executions that can reuse the same runner allocation.
Use the pooled overload for frequent execution, such as each projectile, hit, or frame. For a door that opens twice a session, the plain overload avoids maintaining a pool ID for infrequent allocations.
Fire#
Fire(onComplete, context) starts an Awaitable without awaiting it, attaching a Unity object as context so the framework can report errors against the right object.
Use Fire when you're starting a sequence from a non-async method and don't need the result. In an async method, you can await Run directly when the next operation depends on completion.
Cancellation#
ICancelToken is the framework's cancellation contract — a single Get property meaning stop.
Pass a token to Run when your own object's lifetime should govern the sequence. Implementing it on your component means the Instructions stop when your component decides they should, in the same way an Event's Instructions stop when it's disabled.
Always give long sequences a token
Instructions started from code with no cancellation token keep running after the object that started them is destroyed. If later Instructions access that object, they can produce a null reference error several frames after its destruction.
Where to go next#
- Args — build the context runners need.
- Custom Instructions — write the operations runners execute.
- Events — inspect Event lifecycle from the designer's perspective.