Verse Wiki — the Verse handbook for Blueprint authors
Chapter 1 · Lesson 3

Reading Your First Verse: One Blueprint, Two Ways to Write It

This lesson doesn't teach writing — only reading. We take a mechanic you could build in your sleep — step on a trigger box, play a sound, open a door 3 seconds later — lay that node graph out in your head first, then look at what the same thing looks like as 15 lines of Verse. You leave with 5 rules for reading code, and one conclusion: you can read this stuff.

1. Put That Graph on the Table First

Before looking at any code, do something you've already done a hundred times: build a node graph in your head. The mechanic is unglamorous, but everyone has made it — a player steps on a trigger box, a mechanism sound plays, three seconds pass, the door opens.

How would you wire it in the Event Graph? Roughly these four nodes strung along one white wire:

Order Node What it's doing
1 Event ActorBeginOverlap The overlap event on a trigger box (Box Collision). Something touches it, this red event node fires, and the white wire flows out to the right.
2 Play Sound at Location Play a "clunk". The Sound pin has the audio asset wired in; the Location pin has the door's position.
3 Delay (Duration = 3.0) That latent node with the clock icon. The execution wire parks here for 3 seconds, then continues out of the Completed pin.
4 Open Door (custom function call) Call the open-door function on the door Blueprint. One wire across, and the door opens.

A few things in that graph are so familiar you don't even think about them: one white execution wire strings the four nodes into an order; a few colored data wires feed assets and numbers into the nodes' pins; the variables panel on the left holds the Trigger Box, Sound and Door references; and there's probably a yellow Comment box around the whole thing labeled "pressure plate opens door".

Remember those five things: execution wire, data wire, node, variables panel, comment box. Every single symbol in the 15 lines below maps onto one of them. Really — not one is left over.

2. The Same Graph, as 15 Lines

Below is the same mechanic in Verse. Don't try to understand every character yet — first just scan the shape: the top few lines are "which references exist", the bottom few are "what happens", and it runs straight down the page from top to bottom.

gate_device.verse
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }

gate_device := class(creative_device):

    @editable Pad:trigger_device = trigger_device{}
    @editable Chime:audio_player_device = audio_player_device{}
    @editable Gate:door_device = door_device{}

    OnBegin<override>()<suspends>:void =
        # Park on the next line until somebody steps on the trigger box
        Pad.TriggeredEvent.Await()
        Chime.Play()
        Sleep(3.0)
        Gate.Open()

Now line by line. On the left is the code; on the right is "which thing in your graph this is":

Line Code What this is in your graph
1–2 using { … } Hauling the asset libraries you need within reach. No node on the graph corresponds to this — it's more like "which plugins are enabled in the project". The /Fortnite.com/Devices drawer holds the devices you can drag into a level.
4 gate_device := class(creative_device): Create a Blueprint class with creative_device as the parent — the right-click → Child Blueprint Class step. This class is "the Blueprint that holds the graph".
6–8 @editable Pad:trigger_device = … Three variables in the variables panel, typed as references to a trigger box, an audio player and a door. @editable is the eye icon next to a variable (Instance Editable) — tick it, and you can drag the actual trigger box in on the Details panel in the level.
10 OnBegin<override>()<suspends>:void = The entry point of the Event Graph, playing the same role as Event BeginPlay. Every line below it that is indented further is the white wire pulled out of that event node.
11 # Park on the next line… The yellow Comment box. Written for humans; the machine skips it entirely.
12 Pad.TriggeredEvent.Await() Event ActorBeginOverlap. The execution wire stops right here until somebody steps on the Pad trigger box.
13 Chime.Play() Play Sound at Location. The only difference: Blueprints feed the Sound asset straight into the node, while here Verse tells an audio player device already placed in the level to do the job.
14 Sleep(3.0) Delay, Duration = 3.0. The 3.0 in the parentheses is the number you typed into that pin.
15 Gate.Open() Call the open function on the door. Equivalent to the wire running from the Delay's Completed pin into the Open Door node.

See it? The nodes are all still there. The wires are gone. The same four nodes survive — they just went from "laid out on a canvas and strung together with wires" to "stacked in a column and read top to bottom". The reason the execution wire vanished is humble: text already has an order, so you don't need a wire to say "do this one, then that one". That deserves a page of its own — see the Advanced extra at the bottom.

3. Five Rules for Reading Code

Compress that table and you get five rules. Learn these five, and it's not just this snippet you can read — every Verse fragment on this site is built on the same skeleton.

Rule 1: indentation = wires. Indenting one step (4 spaces) means "I come after the thing above me" or "I'm inside it". Lines 12–15 are all indented inside OnBegin, so they're the four nodes on the white wire pulled out of BeginPlay; lines 6–8 are indented only one step, level with OnBegin, so they aren't nodes at all — they're this Blueprint class's variables. Reading indentation is reading wires: things in the same column are siblings on the same wire, things further right are wrapped inside.

Rule 2: := means create and assign. Read it as "is defined as". Line 4, gate_device := class(…), is "create a thing called gate_device whose content is a class"; data works the same way — MaxPlayers := 12 is creating an integer variable in the variables panel with the default filled in as 12. Note that it's only for creating — changing an existing variable's value has its own syntax in Verse (set, which is that Set node), covered in Lesson 8. And don't confuse it with a lone =: that one compares two things for equality.

Rule 3: Name(arguments) means a node doing work. Any time you see a name immediately followed by a pair of round brackets, that's a node firing. Sleep(3.0) is the Delay node, with 3.0 typed into the pin; the dot in Chime.Play() reads as "'s" — "Chime's Play" — the equivalent of dragging the Chime reference out and pulling a Play node off it. Empty brackets simply mean this node has no input pins to fill.

Rule 4: things inside <> are the node's tick-boxes. The <override> and <suspends> on line 10 are called "specifiers". They aren't arguments — they're labels stuck onto this function, playing much the same role as that row of checkboxes on a Blueprint function's Details panel. <override> ≈ "I'm overriding the parent's function of the same name" (the Override dropdown in Blueprints); <suspends> ≈ "latent nodes are allowed in this function" — it's precisely because that label is there that line 14 is allowed to contain Sleep, just as Delay in Blueprints may live in an Event Graph but not in a pure function. While we're here: the @editable at the start of lines 6–8 is the same kind of thing under a different name ("attribute"), and it corresponds to a variable's Instance Editable checkbox. Reading strategy: skip the angle brackets first, get the trunk of the sentence, then come back for the labels.

Rule 5: a leading # is a comment bubble. Everything from # to the end of the line is for humans; the compiler looks straight through it. It's the yellow Comment box from Blueprints, or the little note pinned to a node. The good news: code comments don't get dragged out of alignment or buried underneath nodes.

Five rules down — now scan the code in section 2 again. This time you should be able to slice it into three blocks at a glance: hauling in the toolboxes (1–2), the variables panel (4–8), the Event Graph (10–15).

4. Line by Line: Making That Graph Move

Rules are static; execution order is alive. The stepper below lights up all 15 lines in the order they run, and every step's note answers exactly one question: which node is this in Blueprints. Click "Run Next Step" and follow along like a replay.

gate_device.verse
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }

gate_device := class(creative_device):

    @editable Pad:trigger_device = trigger_device{}
    @editable Chime:audio_player_device = audio_player_device{}
    @editable Gate:door_device = door_device{}

    OnBegin<override>()<suspends>:void =
        # Park on the next line until somebody steps on the trigger box
        Pad.TriggeredEvent.Await()
        Chime.Play()
        Sleep(3.0)
        Gate.Open()
Output Log

Click "Run Next Step" to watch the code execute line by line.

Look at step 12: the execution wire stops there and waits for a human, possibly for ten minutes. Blueprints behave the same way with Delay and event waits — it's just that on a graph, "waiting" is a node with a clock on it, whereas in code "waiting" is an ordinary line and everything after it queues up politely behind it. That's the confidence behind replacing wires with indentation: order comes for free.

5. Check That You Really Read It

Try a different graph: step on a trigger box → wait 1.5 seconds → turn on a lamp. Two spots have been dug out of the code below, one testing rule 2 and one testing rule 3. Fill them back in:

lamp_device.verse
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }

# Create a Blueprint class whose parent is creative_device — what's the "is defined as" symbol?
lamp_device ____ class(creative_device):

    @editable Pad:trigger_device = trigger_device{}
    @editable Lamp:light_device = light_device{}

    OnBegin<override>()<suspends>:void =
        Pad.TriggeredEvent.Await()
        # This line is the Delay node — what is it called?
        ____(1.5)
        Lamp.TurnOn()

If you got them, notice something: you filled those in by following the shape of the node graph, not by reciting syntax. That's the conclusion this lesson wanted to hand you.

Blueprint Cross-Reference

This lesson, squeezed into one cheat sheet: elements of a node graph on the left, their form in code on the right. The differences column is the important one.

How you do it in Blueprints How it's written in Verse Difference
White execution wire Top-to-bottom line order + indentation No wire can be miswired, crossed, or tangled; the cost is you can no longer "rearrange" logic by dragging nodes — only by cutting and pasting lines
Colored data wires into pins Arguments inside round brackets, e.g. Sleep(3.0) Data flow is written into the call; the upside is "where this value came from" is visible at a glance, the downside is you can't fan one data wire out to several nodes the way Blueprints let you
Right-click → new Child Blueprint Class gate_device := class(creative_device): One line of text replaces creating an asset; the lowercase-with-underscores name is Verse's convention for type names
New variable in the panel + tick Instance Editable @editable Pad:trigger_device = trigger_device{} The checkbox becomes @editable written in front of the name; leave it off and the variable is purely internal, invisible on the Details panel
Event BeginPlay OnBegin<override>()<suspends>:void = Same role, but Verse makes you write <override> explicitly, stating that you know you're overriding the parent's function
Event ActorBeginOverlap Pad.TriggeredEvent.Await() A Blueprint event node "gets called"; this line "stops and waits". Verse has both flavors — the other is subscribing a callback function, covered in Lesson 25
Delay (Duration pin) Sleep(3.0) Delay may only live in an Event Graph; Sleep may only appear in a function labeled <suspends> — the same constraint in different clothing
Call Function node Gate.Open() The dot reads as "'s" — equivalent to dragging the reference out and pulling a node off it. Verse only exposes what Epic explicitly published, so don't guess by copying Blueprint node names
Yellow Comment box / node notes Lines starting with # Can't be dragged out of place or buried under nodes; but you also can't draw a "box around this cluster" visual grouping
Checkboxes on the Details panel Specifiers in <> / attributes starting with @ Blueprint tick-boxes are scattered around the panel; Verse sticks them all next to the name — you read them while reading the code, no window switching

Why do these differences exist? At bottom, one sentence: a node graph binds "logic" and "layout" together, and text code pulls them apart. In a Blueprint, where a node sits on the canvas is both an aesthetic question and a readability question, and a wire expresses both order and data flow; add enough wires and the canvas becomes a ball of yarn. In text, order is expressed by line order, hierarchy by indentation and data flow by brackets — three separate jobs, three separate mechanisms, and the canvas dimension disappears entirely.

None of which says text is strictly better. Graphical Blueprints have one advantage code can't give you: you see the shape of the whole flow at once, which matters most when there are lots of branches. Epic clearly knows this — an Epic survey mentioned a visual scripting layer for Verse (the community calls it "Visual Verse"), but its form has not been announced. Until then, reading code is a required skill. And to be clear on the timeline: Actors and Blueprints are fully supported in UE6 Early Access (targeting late 2027) and the early versions after it; deprecation waits until Scene Graph is mature enough, with no date set, and Epic has committed to shipping conversion tools before any deprecation — but they have not been released yet. What you're learning isn't a replacement. It's a second way to write the same thing.

6. Level Challenge

Three mini-challenges, all about reading — not one asks you to write code. Correct answers earn a star ★; wrong answers can be retried forever.

In Verse, what expresses "this line runs after the line above it"?

Sleep(3.0) in the code corresponds to which node on your graph?

In the line OnBegin<override>()<suspends>:void =, what are the things inside the angle brackets?

Further Reading

Technique · EXTRA

A Four-Step Method for Reading a Node Graph as Code

A reusable translation routine: find the start of the execution wire, follow the white wire into top-to-bottom lines, stuff the data wires into brackets, draw branches as indentation. With one worked exercise.

Open the extra →

Deep Dive · EXTRA

Who Does Verse Look Like: Python, C# and Blueprints Side by Side

The same tiny piece of logic written three ways. Where Verse looks like Python, where it looks like C#, and the four things that belong to it alone — a cure for code fear.

Open the extra →

Advanced · EXTRA

Why Indentation Can Replace Wires: Execution Wires Are Just Order

A white wire is only ever saying one thing: "do this, then that". Write it as text and the order comes for free, which makes the wire redundant — plus how goto got retired.

Open the extra →