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

string & String Interpolation: Teaching Your Code to Speak

Stitching a variable into a sentence in Blueprints takes a row of Append nodes feeding Print String; in Verse it takes one pair of curly braces. This lesson takes string apart piece by piece: dialogue lines in double quotes, the live fill-in-the-blank magic of curly braces {X}, gluing text together with plus, and the art of debug logging with Print — while defusing the brace-escaping landmine every rookie steps on.

1. string Literals: Lines of Dialogue in Double Quotes

Games are full of text: player names, quest descriptions, kill feeds, that little "Sold out" sign in the shop. In Verse, all of it lives in the string type. The most direct way to write a string is a "literal" (Blueprint has no word for this — it is simply the text you type straight into a text box, with no computation nodes wired in) — drop the line verbatim between a pair of double quotes:

string_basics.verse
using { /Fortnite.com/Devices }

npc_device := class(creative_device):

    # Constant string: the opening line is set in stone
    Greeting:string = "Welcome to the Rookie Arena"

    # var string: the title changes with your combat record
    var Title:string = "Apprentice Hero"

Blueprint translation: this is like creating a new Blueprint Class (based on creative_device) and adding two string variables in the variables panel — Greeting is a constant (never wire a Set node to it and the value is welded shut), while Title may change mid-game (a Set node can hook into it later).

Almost anything can go between the quotes: letters, Chinese characters, digits, punctuation, spaces — all legal. Lesson 8's rules still apply here — a variable that never gets a Set node wired in is a constant, its value welded shut; if you want it to change mid-game, wire in a Set node to push the new value (that password is spelled set in Verse).

While we're here, meet a pint-sized relative: char, the single-character type, whose literals use single quotes'e', for instance. In fact, a Verse string's true form is []char — an array of characters lined up in a row. That backstory pays off big in the later array lesson and on this lesson's extra pages. For now, just remember: double quotes hold a sentence, single quotes hold one character.

2. Interpolation {X}: Live Fill-in-the-Blank Inside a String

Fixed lines are dead on arrival; a good log reports a variable's live value. Verse's answer is downright elegant: write a pair of curly braces inside the string and put a variable name in them — Print("Score: {Score}"). The instant it prints, {Score} is swapped for whatever is actually in that slot. The trick is called string interpolation: cut a blank into the line, and Verse fills it in live.

Better yet, what you drop in doesn't have to be text: integers (int) and decimals (float) go straight into the braces — Verse automatically converts the number to text behind the scenes before embedding it, no manual conversion needed. You can even put a small calculation inside, like {Coins * 2}. There is exactly one red line: a lookup that might fail cannot be interpolated directly (grabbing an array element by index, say — go out of bounds and there is nothing to grab). Run a Branch first (written as if in Verse) to confirm the value is there, pull it out safely, then interpolate that result — you only continue if that line goes through. We put this red line on trial in the pitfalls section.

The announcer below chains constants, variables, interpolation and escaping into one run. Click "Run next step" and watch what each line actually does.

announcer_device.verse
using { /Fortnite.com/Devices }
using { /UnrealEngine.com/Temporary/Diagnostics }

announcer_device := class(creative_device):

    HeroName:string = "Nightstalker"
    var Coins:int = 0

    OnBegin<override>()<suspends>:void =
        Print("Welcome back, {HeroName}!")
        set Coins += 30
        Print("Wallet: {Coins} coins")
        Print("Press \{E\} to open your backpack")
Output log

Click "Run next step" to watch the code execute line by line.

Note the last line: to print actual curly braces you must write \{ and \}. Inside a string, braces are reserved for interpolation — which makes them this lesson's number-one pitfall, and Section 4 puts them on trial.

3. Concatenation & Escaping: Text Addition and Secret Codes

Merging two pieces of text takes nothing fancier than the plus sign. For strings, + means append: "Hello " + Name yields a complete greeting; paired with a Set node you can keep appending, which is especially handy when building up a long announcement step by step:

concat_demo.verse
using { /Fortnite.com/Devices }
using { /UnrealEngine.com/Temporary/Diagnostics }

concat_device := class(creative_device):

    var Report:string = "Battle report: "

    OnBegin<override>()<suspends>:void =
        Kills := 3
        set Report += "eliminated {Kills} players, "
        set Report += "survived to the end"
        Print(Report)
        Print("The report is {Report.Length} char units long")

Blueprint translation: when the game starts (Event BeginPlay), Report begins as "Battle report: " and Kills is noted as 3; then two Set nodes append text onto the end (+= means take the old value, attach the new segment, and stuff it back in); finally two Print String nodes output the full report and its length.

That last line quietly spoils string's array backstory: since it is []char, it also has the array's .Length, which returns an int (careful: a Chinese character usually occupies several code units, so this number can be larger than what your eyes count — the extra page has the full story).

Now meet the string's secret code system — backslash escapes. Some characters can't be typed straight into a literal; they need a code that starts with a backslash:

You write You get When to use it
\{ and \} { and } Printing real braces instead of interpolating
\" " Quotes inside a line: he yelled \"Charge!\"
\\ \ Printing the backslash itself
\n Newline Splitting one log entry across two lines
\t Tab Aligning log columns

The rule is easy to remember: any character with special status inside a string — braces run interpolation, double quotes mark boundaries, backslash runs the codes — needs a leading \ to print as-is. You're telling the compiler: this one is exempt from inspection, wave it through unchanged.

4. The Art of Print Debugging (and Common Pitfalls)

Print (Blueprint's Print String node) is your most loyal scout: when code misbehaves, drop a few Print calls at key spots, and the log reports exactly where the program got to and what your variables actually hold. A few veteran tips:

Add a prefix. Print("[Shop] Balance: {Coins}") beats a naked number every time — once logs pile up, unnamed output is no output.
Print before-and-after. One Print before a variable changes and one after makes the state change plain to see — ten times faster than staring at code and guessing.
Tear it down when done. Debug Prints are scaffolding: strip them out once the feature passes, and don't let release logs scroll into a blur.

Next up is this lesson's pitfall patrol — four traps, every one a high-frequency rookie accident:

Pitfall 1: Printing a number directly lights up red. Print String's input pin only accepts text (string); wire an integer or a decimal straight in and the pin types don't match — hit Compile and you get an error. To print a number, let interpolation translate: Print("{42}"), Print("HP: {Health}") — wrap the number in braces and Verse converts it to text automatically. Forget this and Compile reminds you with a red type-mismatch error.

Pitfall 2: Bare braces blow up the moment you hit Compile. Print("Press {E} to interact") looks innocent, but Verse decides {E} is a blank to fill and goes hunting for a variable named E — not found means red errors; and even if an E does exist, what prints is its value, not the three characters "{E}". For real braces, write \{E\} like an honest citizen.

Pitfall 3: A lookup that might fail can't be interpolated directly. Writing "{MyString[0]}" lights up red — grabbing a character by index can come up empty (out of bounds), and interpolation won't accept a maybe-it-fails case. The correct form runs a Branch first (written as if in Verse) to confirm the grab succeeds, then reports in: if (First := MyString[0]) { Print("First char: {First}") } — printing only happens if that line goes through.

Pitfall 4: An interpolated decimal (float) ships with six decimal places. "{1.5}" prints 1.500000 — when Verse converts a decimal to text it always pads to six decimal places, which looks especially jarring in UI text; format it by hand (last lesson's extra page has the rounding recipe).

One last inoculation: Verse's string toolbox is extremely restrained — no Split, Replace, Contains or ToUpper. Those nodes sit right at hand in Blueprint's String node library, but the Verse standard library ships none of them. The community built the missing wheels long ago — see this lesson's extra page.

5. Hands-On Time: Complete the Announcer's Lines

Watching without practicing is fake kung fu. The level-up announcer below has three key pieces carved out: one interpolation, one concatenation operator, one brace escape. Fill them back in, then click "Check answers".

Blueprint translation: at start (Event BeginPlay) a Set node adds 4 to Level; the remaining three blanks are this lesson's trio — interpolation, concatenation, escaping — one of each.

levelup_device.verse
using { /Fortnite.com/Devices }
using { /UnrealEngine.com/Temporary/Diagnostics }

levelup_device := class(creative_device):

    var Level:int = 1

    OnBegin<override>()<suspends>:void =
        set Level += 4
        # Blank 1: report Level with interpolation (braces + variable name)
        Print("Current level: ____")
        # Blank 2: join the two pieces into "Lord Nightstalker"
        Title := "Lord " ____ "Nightstalker"
        Print("Title earned: {Title}")
        # Blank 3: escape the left brace to print "{VIP}"
        Print("____VIP\}")

Blueprint Cross-Reference

Text is one of the places where Blueprints and Verse diverge hardest: Blueprints hand you an entire String node library, Verse hands you a pair of curly braces and stops there.

In Blueprints In Verse Difference
Variable type set to String :string The names line up, but a Verse string really is []char — an array of characters — which is why it has .Length
A row of Append nodes stitching variables into a sentence "Welcome back, {HeroName}!" Interpolation is written inside the string itself — no nodes, no pins; that whole row of Appends collapses into one pair of braces
Print String node Print("…") Blueprint's text pin converts numbers to text for you; Verse doesn't — a number must be wrapped in {} or the types won't match
Concatenate / + to join two pieces of text "Lord " + "Nightstalker" Nearly identical; set Report += "…" is the Set node that takes the old value, attaches the new segment and stuffs it back
Get Character At Index / Len nodes MyString[0] (can fail), Report.Length Grabbing a character by index can go out of bounds, so it must plug into an if; .Length counts code units, not the characters your eye sees
Split / Replace / Contains / ToUpper in the String node library Not in the standard library — write your own This is the lesson's biggest drop: the text tools you reach for casually in Blueprints ship with Verse not at all
The Text type (localizable, meant for UI) message with <localizes> string is bare text; anything headed for UI or translation must be a message, and there is no direct conversion between the two

The differences come from two different ideas of what text is. Blueprints treat a string as data you haul around the graph, so every concatenation, search and replace has to be a node, and a bigger node library is a better one. Verse treats a string as a literal in your source, so joining goes straight inside the quotes (interpolation) while searching and replacing are handed back to you — because a string is an array, and with the for and indexing from later lessons you can write them yourself.

The muscle memory most in need of rebuilding is the String/Text line. In Blueprints you probably barely distinguish them — drop a pin somewhere and it converts. In Verse there is no wire at all between string and message; you have to mint a new one with a <localizes> function. It is a hard cut, but it forces the question at the moment you write your first line of UI text: is this sentence ever going to be translated?

6. Level Challenge ★

Time to grade your scriptwriting fundamentals. Zero penalty for wrong answers — retry as often as you like.

You want the variable Kills (an int) in the log and write Print(Kills). What happens?

You want an actual pair of curly braces {} printed in the log. The correct way to write it is?

What does Print("{1.5}") output?

Further Reading

Technique · EXTRA

Build Your Own Split

No Split in the standard library? The community built the wheel long ago — one function that drills every skill from this lesson.

Enter the extra →

Deep Dive · EXTRA

message & <localizes>

Why isn't UI text a string? A wall every creator hits, and the standard way over it.

Enter the extra →

Advanced · EXTRA

Strings Under the Hood: char, char32 & UTF-8

Why is 'e' a char but 'é' a char32? Text encoding demystified in one sitting — especially practical when you work with Chinese text.

Enter the extra →