Skip to content

Visual scripting

Opal's visual scripting system — Flow — works like Unreal Blueprints. You connect nodes on a canvas to define what happens when events fire. No code required for most games, though you can drop in Expression and Script nodes when you need more power.

There are two scopes:

ScopeWorkspace tabRuns on
Object FlowObject FlowOne object — its taps, drags, collisions, timers, …
Scene FlowScene FlowThe whole scene — startup, transitions, global rules

Both use the same node catalog, inspector, and wire types.

Prefer typing to wiring?

Any graph can also be edited as readable text — hit the Text button in the flow toolbar. See Flow as text.


Graph anatomy

Rules

Each graph is a rule: a trigger event plus the nodes wired beneath it. One object (or the scene) can have many rules — for example separate graphs for On Tap and On Scene Start.

Wires

Wire colorCarries
WhiteExecution — "run this next"
ColoredData — numbers, booleans, text, object references

Click an output port and drag to a compatible input to connect. Data ports and wires use their value type's color, while execution wires stay white. Click a wire or node and press Delete to remove it.

Node catalog

The catalog on the side groups nodes by category:

  • Lifecycle — On Scene Start, On Created, On Destroyed, …
  • Input — On Tap, On Drag, On Key Down, …
  • Drag & Drop — drop targets, pickup events
  • Area / Collision — pointer enter/exit, physics collision events
  • State & Variables — set/read GameState and object variables
  • Sprite Animation — set Animation State, play motion, set visibility, VFX
  • Timers — delay, repeat, stopwatch
  • Spawn / Destroy — create prefabs, remove objects
  • Components — actions and conditions from attached components (Health, Inventory, …)

When you attach components to an object, that object's catalog gains matching Component Action and Component Condition nodes automatically.


Your first graph

Example: play a sound when the player taps an object.

  1. Select the object in Arrange
  2. Switch to Object Flow
  3. Click + Event (or double-click the canvas) and pick On Tap
  4. From the catalog, add Play Audio
  5. Connect the white execution pin: On TapPlay Audio
  6. In the Flow inspector, choose a sound asset for the node
  7. Press Play and tap the object

Event categories (common)

Input events

EventFires when
On TapQuick press-and-release on the object
On Double TapTwo taps in quick succession
On Long PressPress held past a threshold
On Drag Start / Drag / Drag EndPointer drag gestures
On Pointer Enter / LeaveHover in/out (desktop)

Objects need an Interactable (or legacy Tappable) component — or an On Tap graph, which adds Interactable — for most pointer events to fire.

Lifecycle events

EventFires when
On Scene StartScene begins (Scene Flow)
On CreatedObject is spawned or scene loads
On DestroyedObject is removed

Drag and drop

Use Drop Zone component or drop / droppedOn flow events for drag-and-drop puzzles, inventory, and card games. The dragged object is the source; the target is where it was dropped.

Timers

On Timer and Start Timer / Stop Timer nodes drive delayed and repeating logic without code.


Scene Flow vs Object Flow

Object Flow graphs are stored on the selected object. The On Tap trigger only fires for taps on that object unless you parameterize a different target in action nodes.

Scene Flow graphs live at scene scope. Use them for:

  • Loading UI on On Scene Start
  • Go To Scene when the player wins or loses
  • Global timers and score tracking
  • Listening for Custom Events broadcast from any object

Switch to the Scene Flow tab to author scene rules. The catalog and inspector behave the same way.


Expressions

Many node fields accept expressions — small snippets evaluated at runtime. Prefix a field with = (or use the expression toggle) to switch from a literal value to a formula.

Examples:

text
=self.hp + params.amount
=Math.min(self.hp, 5)
=get("health")?.hp

Available context in Flow = expressions (varies by node):

SymbolMeaning
selfOften the component fields for a component action/condition; otherwise may be null
thingThe resolved scene object for the node
paramsParameter / event payload bag
event / source / targetActive event and actors
get("health")Sibling component fields on thing
MathStandard Math object

For GameState and object variables, prefer the dedicated Get / Set variable / Add Counter (catalog) nodes rather than inventing a bare GameState.score identifier in a Flow expression — that form is not bound in the Flow evaluator. In UI bindings, project variables are available as self.score or self.GameState.score (see UI and HUD).

Expressions are optional — literal values and data wires work fine for simple graphs.


Variables

GameState (global)

Declare variables in the top bar Variables menu. Types: Number, Bool, Text.

In graphs:

  • Set variable / Add Counter (writes a number GameState field)
  • Variable at least / comparisons — branch on GameState
  • Get / Set Value nodes targeting scene / GameState keys

GameState persists across Go To Scene (same play session) unless you reset it.

Object variables

In Arrange → Inspector → Variables, declare per-object fields. Read and write them with Get/Set value nodes (object scope) or autocomplete in rule fields. At runtime they live on thing.vars.


Branching and conditions

Use If / Condition nodes (or component condition nodes like health.isAlive) to split the white execution wire:

text
On Tap → health.isAlive?
           ├─ true  → Play Audio
           └─ false → Spawn VFX (death poof)

Condition nodes output which execution pin to follow.


Custom events

Emit Event broadcasts a named custom event. On Custom Event listens for it. Choose scope:

ScopeReaches
SceneListeners in the current scene
LocalSame object hierarchy
GlobalProject/session listeners
TargetedOne specific object or group

Custom events decouple systems — e.g. a button emits GameOver and Scene Flow handles the rest.


Testing while authoring

  • Play in viewport — full runtime test
  • Live Flow overlay — while playing, toggle Flow on the canvas overlay to see nodes light up as they run
  • Per-rule Test control in the flow UI — fires a synthetic event for that graph without full play (where available)

Ctrl+Z undoes graph edits (node moves and multi-node deletion each collapse into one step). Press A to open the add palette at the canvas center, or double-click the exact place you want to add. Ctrl/Cmd+D duplicates selected nodes inside an open graph.


Tips

  1. One event, one rule — easier to read than giant graphs; duplicate rules when needed
  2. Name your rules — the flow list gets long on complex objects
  3. Component nodes — prefer health.damage over manual variable math when a component already models the behavior
  4. Scene Flow for globals — don't duplicate win/lose logic on every object
  5. Prefabs carry graphs — save a configured object as a prefab; instances inherit its Object Flow

Opal Engine — MIT licensed