What “Dragging a Blueprint Into the Level” Really Is in Verse
The last step of the main lesson was “drag the class into the level”. You have done that move hundreds of times in Blueprint, but you may never have asked what it actually does — it turns a drawing into a real thing on the field. This page separates “class” and “instance” for good, then answers a question the main lesson left buried: why can a Verse class field be left without a default value?
1. The Class Is the Drawing, the Instance Is the Thing on the Field
The BP_MyDoor you see in the Content Browser is a class — a drawing describing “what variables a door should have and what it does when it opens”. It is not itself in the world; it is only the specification.
Drag it into the Viewport and the World Outliner gains a row called BP_MyDoor_C_0. That is an instance: it has coordinates, its own copy of every variable value, and it gets woken by Event BeginPlay. Drag another and you get a second instance, BP_MyDoor_C_1, living its own life alongside the first.
The relationship carries over into Verse without a single change:
my_door := class(creative_device):defines the class — the drawing;- the thing you drag into the level after building is the instance;
- drag two in and
OnBeginruns twice — independently, each instance carrying its own copy of the field values. That is exactly what the main lesson meant by “every copy you drag in runs its own logic”.
While we are here, two operations beginners often conflate — and they behave identically on both sides: editing the class (the Blueprint asset / the Verse code) affects every instance; editing one instance’s Details panel affects only that one.
2. Instantiation: One Move, Two Routes
Making a real thing from a drawing is called instantiation. Blueprint offers two routes to it, and so does Verse.
Route one: place it in the editor
Blueprint: drag the asset into the Viewport. Verse: drag the build output into the level. On this route you write no code at all — the editor creates the instance for you. This is also why the main lesson insisted that a class never dragged into the level executes zero lines: the drawing is sitting in a drawer and nobody has built from it.
Route two: build one in code
Blueprint: wire in a Spawn Actor from Class node and conjure one at runtime. Verse does the same job with a pair of curly braces:
# The class: a drawing. It does not inherit creative_device, so it cannot be
# dragged into a level - it can only be built in code
door_config := class:
DoorName:string = "North Gate"
OpenSeconds:float = 1.5
# Instantiation: curly braces = "build one from this drawing"
# Fields named inside get overridden; the rest keep their defaults
SouthDoor := door_config{DoorName := "South Gate"}
door_config{...} is the Spawn node. That DoorName := "South Gate" inside the braces corresponds to the “Expose on Spawn” input pins on a Spawn Actor node — while building this particular one, hand it a setting different from the default. OpenSeconds, never mentioned in the braces, stays at the drawing’s 1.5.
Note that the class above has no parent (class: goes straight into its body). That is deliberate: it shows that not every Verse class has to be a device. The creative_device inheritance exists only to satisfy the runtime requirement “can be dragged into a Fortnite level”; pure data classes and utility classes that never need placing are just ordinary classes, built in code.
3. Why a Class Field May Have No Default Value
Lesson 8 will introduce a rule: constants and variables declared inside a function or a module must be given an initial value on the spot — there is no “hang a blank tag now, engrave it later”. Class fields are the exception: they may declare a type and no value at all.
door_config := class:
# No = value: this tag leaves the factory blank
DoorName:string
# Has a default: leave it alone and it stays 1.5
OpenSeconds:float = 1.5
# Building an instance must fill the blank one, or the build fails
NorthDoor := door_config{DoorName := "North Gate"}
Why is that allowed? Because a class field and a local constant come into effect at different moments. A local constant needs its value the instant execution reaches that line, or the next line has nothing to work with. A class field belongs to something that has not been built yet — a blank on a drawing does not mean the blank stays empty forever; it just defers the question of who fills it to the moment of instantiation.
So the rule collapses into one sentence: if a field has no default, whoever creates the instance is responsible for supplying it. And “whoever creates the instance” is exactly the two routes from the last section:
- built in code → it must appear inside the curly braces, or the build fails;
- placed in the editor → the person who drags it into the level fills it in the Details panel.
The second is the scenario Blueprint authors know best. In Blueprint you tick Instance Editable on a variable (the little eye icon next to it) and it appears in each instance’s Details panel, so every placed instance can carry a different value. The Verse equivalent is @editable:
using { /Fortnite.com/Devices }
my_door := class(creative_device):
# @editable: this field shows up in the instance's Details panel
@editable
DoorName:string = "North Gate"
# No @editable: invisible in the level, only code can change it
OpenSeconds:float = 1.5
With @editable, drag two my_door instances into the level and the Details panel lets you name one “North Gate” and the other “South Gate” — one drawing, two differently configured instances. That is Blueprint’s little eye icon.
A practical caveat: in today’s UEFN, an @editable field generally needs a default value so the editor has something to display — for device-reference types the common idiom is an empty instance as a placeholder (for example button_device{}). So the freedom to omit a default is mostly used on the code-instantiation route.
4. Blueprint Cross-Reference
| How you do it in Blueprint | How you write it in Verse | Difference |
|---|---|---|
The BP_MyDoor asset in the Content Browser (the class) |
my_door := class(creative_device): |
Both are drawings. The Verse drawing is text, and one file can hold several |
| Drag into the Viewport; the Outliner gains a row (the instance) | The build output you drag into the level | Identical move: the editor does the instantiating and you write no code |
| Spawn Actor from Class node (building an instance at runtime) | door_config{DoorName := "South Gate"} |
Verse uses curly braces, and any field can be assigned inside them without first being marked Expose on Spawn |
| Tick Instance Editable (the little eye) → appears in the Details panel | Put @editable in front of the field |
Same effect. Verse replaces a checkbox with a one-line annotation |
| Change a default in Class Defaults → affects every instance | Change the field’s default value in the class | Identical: edit the drawing and everyone changes; edit an instance and only that one does |
A Verse class contains DoorName:string with no default value. What happens?
5. Sources
This page is distilled from Epic’s official documentation: