Generate UI Grids Dynamically with Verse Loops
What you'll learn
You will learn how to:
- Use nested
forloops to iterate over rows and columns - Convert loop indices into pixel offsets with
floatarithmetic - Build
canvas_slots withAnchorsandOffsetsfor absolute pixel layout - Add a
canvaswidget to each player's screen viaGetPlayerUIandAddWidget - Use
GetPlayerUIcorrectly inside a<decides>(failure) context
How it works
Canvas and canvas_slot
The canvas is a free-form container. You push children onto it at runtime with Canvas.AddWidget(Slot:canvas_slot). Each canvas_slot carries:
- Anchors — an
anchorsstruct withMinimum/Maximumvector2values in 0.0–1.0 screen fractions. Pinning both to{X:0.0, Y:0.0}anchors the slot to the screen's top-left corner. - Offsets — a
margin(Left,Top,Right,Bottom) that shifts the widget in pixels from its anchor. With a top-left anchor,Left/Topbecome the absolute pixel position. - Widget — the actual child widget to display.
Grid math
For a grid with Cols columns spaced CellSize pixels apart, the X offset of column Col is just OriginX + (Col * CellSize). Rows work the same way with Row. Because Col is an int and CellSize is a float, we cast with Col * 1.0 before multiplying so the types line up.
GetPlayerUI is a <decides> call
GetPlayerUI(Player) has the <decides> effect — it can fail if a player has no UI. That means you MUST call it in a failure context: if (PlayerUI := GetPlayerUI[Player]):. The bound PlayerUI is a plain player_ui handle (NOT an option). Calling it as a bare statement triggers compiler error 3512.
Let's build it
using { /Fortnite.com/Devices }
using { /UnrealEngine.com/Temporary/UI }
using { /UnrealEngine.com/Temporary/SpatialMath }
using { /Verse.org/Simulation }
using { /Fortnite.com/UI }
# Builds a Rows x Cols grid of text labels on every player's screen UI.
dynamic_ui_grid_device := class<concrete>(creative_device):
@editable Rows : int = 3 # number of grid rows
@editable Cols : int = 4 # number of grid columns
@editable CellSize : float = 80.0 # pixel spacing between cell origins
@editable OriginX : float = 100.0 # top-left X offset, in pixels
@editable OriginY : float = 100.0 # top-left Y offset, in pixels
OnBegin<override>()<suspends> : void =
# One canvas holds every cell for the whole grid.
GridCanvas : canvas = canvas{}
# Nested loops: Row 0..Rows-1, Col 0..Cols-1.
for (Row := 0..Rows - 1):
for (Col := 0..Cols - 1):
# Index -> pixel position (cast ints to float for the math).
PixelX : float = OriginX + (Col * 1.0 * CellSize)
PixelY : float = OriginY + (Row * 1.0 * CellSize)
# Each cell is a simple text label.
CellWidget : text_block = text_block{
DefaultText := StringToMessage("[{Row},{Col}]")
}
# Pin to top-left (anchor 0,0); place via pixel Offsets.
Slot : canvas_slot = canvas_slot{
Anchors := anchors{
Minimum := vector2{X := 0.0, Y := 0.0},
Maximum := vector2{X := 0.0, Y := 0.0}
},
Offsets := margin{
Left := PixelX, Top := PixelY,
Right := 0.0, Bottom := 0.0
},
Alignment := vector2{X := 0.0, Y := 0.0},
SizeToContent := true,
Widget := CellWidget
}
# Add this cell to the canvas at runtime.
GridCanvas.AddWidget(Slot)
# Push the finished canvas onto each player's HUD.
for (Player : GetPlayspace().GetPlayers()):
if (PlayerUI := GetPlayerUI[Player]):
PlayerUI.AddWidget(GridCanvas)
StringToMessage<localizes>(Value : string) : message = "{Value}"```
## Try it yourself
1. In UEFN, create a new Verse file, paste the class, and **Build Verse Code**.
2. Drag the `dynamic_ui_grid_device` from the Content Browser into your level.
3. In the Details panel, set `Rows`, `Cols`, and `CellSize` to taste.
4. Launch a session — every player should see the grid of `[Row,Col]` labels in the top-left.
5. Change `Cols` to `6` and rebuild: the grid widens with a single edit, proving the loop-driven layout.
## Recap
- Nested `for` loops over `0..Rows-1` and `0..Cols-1` generate one cell per iteration.
- Loop indices become pixel offsets via `Origin + (Index * 1.0 * CellSize)`.
- A top-left anchor (`Minimum`/`Maximum` both `0,0`) plus `Offsets` gives absolute pixel placement.
- `GridCanvas.AddWidget(Slot)` builds the grid at runtime; `PlayerUI.AddWidget(GridCanvas)` shows it.
- `GetPlayerUI[Player]` is a `<decides>` call and must live inside an `if` failure context.
Check your understanding
Test yourself with an interactive quiz and track your progress + earn XP — free for members.
Want this as a guided course?
Build your own free, step-by-step lesson plan on Dynamic UI Grid Generation via Verse List Iteration — or pick any topic. Create a free account and the course builder turns it into compile-checked lessons, worked examples, and quizzes, tailored to your level.
© Biloxi Studios Inc. — original Verse Island content.
Original tutorial generated by Verse Island from the indexed Verse/UEFN knowledge base, with references to the Epic Games sources above. Code is validated against the knowledge base.