Tip · EXTRA
Rounding to Any Number of Decimal Places
RoundToDecimalPlaces, from an Epic staffer — one function that threads together every point in this lesson.
Open Extra →Drag an int pin onto a float pin in Blueprints and the editor quietly inserts a conversion node for you; Verse refuses to do you that favour. Gold count is an int; cooldown seconds are a float — to Verse, these are two completely different slot types, and mixing them is forbidden. This lesson covers numbers in full: arithmetic, the idiomatic way to convert between types, why integer division must be wired into a Branch node (if), plus a run-in with a strange guest called NaN.
Last lesson you learned to open slots (var) and swap what's inside (set). This lesson meets the two residents that live in those slots most often — numbers. First up, int: the whole-number slot. Gold count, kills, ammo remaining — anything you can count one by one belongs to it. When filling in its value you can use decimal, or hexadecimal starting with 0x: 0xFF is 255.
Add, subtract, and multiply work freely on int, chained with last lesson's set incantation:
using { /Fortnite.com/Devices }
using { /UnrealEngine.com/Temporary/Diagnostics }
gold_vault_device := class(creative_device):
# Decimal or hexadecimal — both come out as int
var Gold:int = 250
ColorMask:int = 0xFF
OnBegin<override>()<suspends>:void =
set Gold += 50
set Gold *= 2
Print("Gold: {Gold}")
Graph translation: this code is like creating a Blueprint class named gold_vault_device (with creative_device as its parent class — once built, you can drag it into the level). It opens two variables — Gold (int, default 250) is a regular variable; ColorMask has no var, so it's a locked constant that no Set node may touch. OnBegin is Event BeginPlay: the moment the game starts, one Set node adds 50 to Gold, another Set node doubles it, then Print String pushes the result to the top-left of the screen.
After the two-step combo, (250 + 50) × 2, the log reports Gold: 600. Sharp eyes will notice that division / never showed up — in Verse it's a special character, special enough to get a section of its own (see Section 4).
How big a number can an int hold? The official docs give a straight answer: the current implementation is a 64-bit signed integer, ranging from -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807 — roughly ±9.2 quintillion, more than enough for every coin on the server combined. But if a calculation genuinely overflows, Verse won't silently loop around into a negative number the way some older languages do — it throws a runtime error instead. Better to crash on the spot than hand you a wildly wrong number with a straight face. The docs also preview that in a future version, int will semantically become an arbitrarily sized integer, at which point even this ceiling disappears.
One more piece of world-building: every comparison (<, <=, >, >=, =, <>) in Verse is really asking "can this wire go through?" — if the comparison holds, the wire goes through and hands over the compared value; if not, that wire is blocked. So they always plug into a Branch node (if); Verse's Branch doesn't ask True/False — it asks "does this go through?", and if it doesn't, execution takes the else pin instead, e.g. if (Gold >= 600):. This rule runs through the entire book, and we'll use it again before this lesson is over.
float is the decimal slot: movement speed, cooldown seconds, damage multipliers — those light-green float pins in your Blueprints are exactly this. It's high precision (IEEE 64-bit floating point), but the syntax has one iron rule: when writing a float value you must include the decimal point. To say "one point zero" you write 1.0; write 1 and it's an int — to Verse the two have nothing to do with each other. Negatives use the prefix minus: -3.2.
using { /Fortnite.com/Devices }
using { /UnrealEngine.com/Temporary/Diagnostics }
using { /Verse.org/Simulation }
cooldown_device := class(creative_device):
var Cooldown:float = 4.5
OnBegin<override>()<suspends>:void =
set Cooldown *= 2.0
set Cooldown /= 3.0
Print("Cooldown: {Cooldown}")
Sleep(Cooldown)
Print("Skill ready")
Graph translation: one variable Cooldown (float, default 4.5). When Event BeginPlay fires: a Set node multiplies it by 2.0, another Set node divides it by 3.0, Print String shows the current value, and then comes a Delay node — Sleep(Cooldown) means "wait Cooldown seconds". That's also why the signature carries <suspends>: the function body contains a node with the little clock icon (latent), so the wire calling it must be able to stop and wait. Once the wait is up, another Print String reports "Skill ready".
4.5 × 2.0 ÷ 3.0 = 3.0, so Sleep(Cooldown) puts the device to sleep for three seconds — note that Sleep's parameter type is float; passing an int is an instant compile error. Also check the log: it prints Cooldown: 3.000000. Float-to-string always carries six decimal places, and that tail of zeros loves to jump-scare anyone building UI text (the extra page has an Epic staffer's "keep N decimal places" recipe).
Float division has a completely different temperament from int's: it is not one of those "might not go through" operations — dividing by 0.0 won't break the wire. As for what value 1.0 / 0.0 actually produces, the official docs don't commit to an answer; to be rigorous, trust in-editor testing and the Verse API Reference.
One strange guest also lives in the float household: NaN (Not a Number). Verse lays down three house rules for it, each one a deliberate departure from the IEEE-754 standard: the whole language has exactly one NaN; NaN = NaN succeeds — NaN equals itself; and NaN takes part in comparisons, ranking greater than every other float. These three rules give Verse's floats a “total order” — any two floats can be ranked against each other, so sort results are always deterministic, never flaky. The price: if a NaN sneaks into a pile of data, Max will fish it out as the maximum. The guest's full dossier is on this lesson's extra page.
Tap the blackboard — the most important discipline of this lesson: int and float never mix, and never convert automatically. Blueprint veterans, watch out here — in Blueprints, dragging an int pin onto a float pin quietly inserts a conversion node for you; Verse refuses to do you that favor: 1 + 1.0 is a straight compile error (Compile lights up red), and Sleep(5) won't compile either — it must be Sleep(5.0).
# Neither line below compiles: int and float refuse to mix
Broken1 := 1 + 1.0
Sleep(5)
# The right way: same-type math, arguments matching the declared type
Fine := 1.0 + 1.0
Sleep(5.0)
So what about when you do need to convert? Two directions, two moves:
int → float: multiply by 1.0. The idiom is KillsAsFloat := Kills * 1.0. No magic here — the * operator itself allows "one side int, one side float" multiplication, and the result comes out as a float. Verse has no ready-made "to float" node or function; multiplying by 1.0 is the officially sanctioned bridge.
float → int: rounding functions that might not go through. Floor[X] rounds down, Ceil[X] rounds up, Round[X] rounds to nearest. Note that they're called with square brackets — in Verse, square brackets are the warning that "this step might not go through": when X is NaN, or too large for an int to hold, the rounding fails and the wire is blocked. So they too must plug into a Branch node (if): if (N := Floor[3.7]):.
Watching without practicing is fake kung fu. The converter below has had two key parts pried out: the bridge that turns int into float, and that round-down function that might not go through. Put them back, then hit Check Answer.
using { /Fortnite.com/Devices }
using { /UnrealEngine.com/Temporary/Diagnostics }
convert_device := class(creative_device):
Kills:int = 7
OnBegin<override>()<suspends>:void =
# int → float: multiply by a special decimal
KillsAsFloat := Kills * ____
# float → int: the failable round-down function, square-bracket call
if (Half := ____[KillsAsFloat / 2.0]):
Print("Halfway tally: {Half}")
Time for the benched division operator to take the stage. int's / comes with two startling rules. First, it might not go through — whenever the divisor is 0. So X / 2 can't just be wired into an ordinary execution line; it must plug into a Branch node (if) that first checks whether it goes through, or Compile lights up red and bounces it back. Second, its result is neither int nor float but a third numeric type, rational: 5 / 2 yields the exact fraction 5/2, with not a shred of precision lost. Want your int back? You must answer out loud which way the remainder rounds: Floor(...) goes down (toward negative infinity), Ceil(...) goes up. In some older languages 5 / 2 just quietly becomes 2 (decimals chopped off); in Verse you spell it out as Floor(5 / 2) — the rounding direction in black and white, and nobody sneaks past.
There's no % symbol for remainders — use Mod[A, B] instead (square brackets = this step might not go through; divisor 0 makes it fail). While you're here, bank a batch of built-in math functions — Abs, Min, Max, Sqrt, plus the float-flavored Pow: the same math nodes you've been wiring in Blueprints all along. The loot splitter below runs division, rounding, and remainder in a single heist — hit Run Next Step and watch it divvy up the gold line by line.
using { /Fortnite.com/Devices }
using { /UnrealEngine.com/Temporary/Diagnostics }
loot_split_device := class(creative_device):
# The loot: 7 gold coins, 2 players
TotalGold:int = 7
Players:int = 2
OnBegin<override>()<suspends>:void =
if (Share := Floor(TotalGold / Players)):
Print("Each player gets {Share} gold")
if (Extra := Mod[TotalGold, Players]):
Print("{Extra} left over, into the guild vault")
Hit Run Next Step to watch the code execute line by line.
Tweak the parameters in your head: if Players were 0, the division on line 11 wouldn't go through, the whole Branch (if) wouldn't hold, and not a single Print String inside would run — no crash, no exception; the blocked wire is caught cleanly by the Branch, which routes to else instead. That's the Verse way: turning the divide-by-zero accident from a runtime bomb into a discipline you must settle at Compile time.
Below are the eight incidents beginners log most often on the numeric assembly line, each filed with its cause and its cure. Scan through — the QA station will quiz you shortly.
| Symptom | Cause | Cure |
|---|---|---|
Casually write Half := X / 2; it won't compile |
int division might not go through (the divisor might be 0) and must plug into a Branch node (if) | if (Half := Floor(X / 2)): |
Assume 5 / 2 equals 2 |
The result is the exact fraction rational 5/2 — Verse won't chop decimals behind your back | Pick the direction yourself: Floor(5 / 2) gives 2, Ceil(5 / 2) gives 3 |
Sleep(5) is a compile error |
Sleep wants a float; int won't convert automatically | Write Sleep(5.0) |
set MyInt /= 2 won't compile |
int division might not go through, so it can't squeeze into a one-step self-update like /= |
/= is fine on float variables; int has to do it properly with a Branch (if) + Floor |
Reach for % to get a remainder — no such symbol |
Verse has no % operator | Mod[A, B] (square brackets = might not go through) |
The UI shows 1.500000 |
Float-to-string always carries six decimal places | See the extra page "Rounding to Any Number of Decimal Places" |
| Assume NaN equals nothing | Verse deliberately departs from IEEE-754: NaN = NaN succeeds, and NaN ranks largest |
When data may contain NaN, screen it with a comparison before handing it to Max or a sort |
| Multiply big numbers together; the game errors out mid-run | int overflow is a runtime error, not a silent wraparound | Mind the 64-bit range; cap values early where needed |
You have been wiring Blueprint's math nodes for years. Most of the names map straight across; what actually needs relearning is when the editor stops covering for you.
| In Blueprints | In Verse | Difference |
|---|---|---|
| Variable type set to Integer / Float | :int / :float |
The names line up, but a Verse float literal must carry the decimal point: 1.0 is a float, 1 is an int |
| Drag an int pin onto a float pin; the editor inserts a conversion node | Kills * 1.0 |
Blueprints convert for you, Verse makes you spell it out — and there is no ready-made "To Float"; multiplying by 1.0 is the official bridge |
| Truncate / Floor / Ceil / Round nodes | Floor[X] / Ceil[X] / Round[X] |
Verse uses square brackets to warn you the step might not go through (X is NaN, or too big for an int) |
| Divide node: two integers in, a truncated integer straight out | Floor(A / B), and the whole line must plug into an if |
Blueprints truncate by default and tolerate divide-by-zero; Verse's / can fail, its result is the exact fraction rational, and you name the rounding direction |
| The % (Modulo) node | Mod[A, B] |
Verse has no % operator at all; the square brackets again flag that a zero divisor fails |
| Abs / Min / Max / Square Root / Power nodes | Abs / Min / Max / Sqrt / Pow |
Same names, same meanings — you just write the function name instead of dragging a wire |
| Integer overflow silently wraps around into a negative | Overflow throws a runtime error | Verse would rather stop on the spot than hand you a wildly wrong number with a straight face |
These differences share a single source. Blueprints are an editor built to help you connect things: pins that don't match get a conversion node, division by zero gets a quiet 0 back. Verse is a compiler built to stop you connecting things: wherever something could go wrong at runtime, it drags the problem forward to Compile time and makes you deal with it in the open. Integer division lives inside an if not because the language enjoys the friction, but because "the divisor might be 0" is baked into the type — there is no way around it.
The good news is that this tuition is paid once. After the adjustment, you'll notice that the afternoons Blueprints used to cost you — a value inexplicably off by one, a progress bar that never quite reaches 100% — no longer have a chance to happen, because every rounding direction and every failure branch was written down by your own hand.
Congratulations — you've been appointed QA inspector of the numeric assembly line. Three batches of code are rolling in on the conveyor; some can pass, some must be stopped. Deliver your verdicts. Zero penalty for wrong answers — retry as often as you like.
Batch one: on an ordinary execution wire, a lone line Half := X / 2 (X is an int). Your verdict?
Batch two: Total := Kills + 0.5 (Kills is an int). Your verdict?
Batch three is a theory question: which statement about NaN is true in Verse?
Tip · EXTRA
RoundToDecimalPlaces, from an Epic staffer — one function that threads together every point in this lesson.
Open Extra →Advanced · EXTRA
Integer division returns neither int nor float — meet the overlooked exact fraction.
Open Extra →Deep Dive · EXTRA
Three bold amendments to IEEE-754 that give float a total order.
Open Extra →