Skip to content
Berke edited this page Oct 10, 2026 · 3 revisions

UI Text

Inspector name: Text · Lua: entity.uiText · Public field type: not available

A Text component draws text on the HUD: scores, ammo counts, messages, timers.

How it works

  • The text starts at the top-left corner of the entity's UI Transform rectangle, inset from the left and top edges (8 pixels at the UI Reference Height).
  • It is drawn in its Color (white by default), in its Font (the engine's default font, Noto Sans, when none is set) at its Font Size.
  • Color is RGBA, each channel 0..1, like a Sprite's. Unlike sprites and UI images, text really is blended: an alpha of 0.5 makes it half see-through, and 0 hides it. Sector light never affects it.
  • The UI Transform's size is only used to find that corner: text isn't scaled to fit, isn't wrapped and isn't clipped. Long text runs past the rectangle.
  • A new line (\n, or Enter in the inspector) starts a new line of text, one line height below.
  • The UI Transform's rotation doesn't turn text.
  • Text is drawn after every Image, so it always appears on top.

Because only the top-left corner matters, the easiest way to place text is with the pivot at 0, 0 and the anchor where you want the text to start. Centring text isn't automatic: the width of the text isn't known to scripts.

Fonts

Any .ttf or .otf file under Assets can be a Text's font. The Asset Browser shows them as font assets: drag one onto the Font field (or double-click it, then click the field). Clear goes back to the default font.

  • The Font is stored as the file's path inside Assets, with its extension, e.g. "Fonts/title.ttf". Renaming or moving the file in the Asset Browser updates the Texts in the open level that use it.
  • A font that can't be loaded (wrong path, broken file) is reported in the log once, and the text is drawn in the default font instead.
  • Exported games include every file in Assets, so the font ships with the game.

Characters

Text is UTF-8, so any language works: "Ölüm", "Привет", "→ ★". Each character is prepared the first time it is drawn, so there's no list of supported characters to set up.

If the Text's font doesn't have a character, it is taken from the default font (Noto Sans covers Latin, Greek and Cyrillic). If neither has it, the font's "missing character" box is drawn and the log says which character was missing, once.

Size and the UI Reference Height

Font Size is the text's size in pixels at the project's UI Reference Height, set in Project Settings > UI (default 1080). The text is drawn at:

drawn size = Font Size × window height / UI Reference Height

So with the defaults, a Font Size of 48 is 48 pixels tall in a 1080-pixel-tall window and 24 pixels in a 540-pixel one: text keeps its size relative to the screen. The 8-pixel inset scales the same way. UI Transform positions and sizes are still plain pixels and do not scale, so very different window sizes can move text relative to its rectangle's other edges.

A Font Size of 0 hides the text. The largest drawn size is 512 pixels.

The UI Editor's canvas previews each Text in its own Font and Font Size, at the editor window's height.

In the editor

In the UI Editor: Add Text Component.

Field Lua Default Notes
Text text empty What to show. Enter starts a new line.
Font font empty (default font) A .ttf / .otf from the Asset Browser. See Fonts.
Font Size fontSize 48 Pixels at the UI Reference Height. See Size.
Color color 1, 1, 1, 1 RGBA, 0..1. Alpha below 1 makes the text see-through.

Scripting

Property Type Description
isValid boolean read-only false if the entity or its Text is gone.
text string read/write Shown from the next frame. UTF-8; \n starts a new line.
font string read/write Font path relative to Assets, with its extension, e.g. "Fonts/title.ttf". "" = the default font.
fontSize number read/write Pixels at the project's UI Reference Height. 0 or less hides the text.
color Vector4 read/write RGBA, each 0..1. color.w is the alpha.
-- A title that's bigger and uses its own font.
local title = entity.uiText
title.font = "Fonts/title.ttf"
title.fontSize = 96
title.color = Vector4(1, 0.8, 0.2, 1) -- gold
title.text = "Level 1\nThe Hangar"

Fade text out

-- Scripts/UI/FadeOut.lua (UI entity with a Text): fades the text out over `duration` seconds.
public number duration = 2

local elapsed = 0

function Update()
    elapsed = elapsed + GameTime.deltaTime
    local c = entity.uiText.color
    entity.uiText.color = Vector4(c.x, c.y, c.z, math.max(0, 1 - elapsed / duration))
end

A colour read from color is a copy, so change it and assign it back, as above.

Changing font or fontSize often is fine: each font is loaded once, and characters at a new size are prepared the first time they're drawn.

Build strings with .. and tostring, or string.format for number formatting:

entity.uiText.text = string.format("Time %02d:%02d", minutes, seconds)

Only write text when the value actually changes. Setting it every frame works, but it's wasted work.

Examples

Timer

-- Scripts/UI/Timer.lua (UI entity with a Text)
local elapsed = 0
local shown = -1

function Update()
    elapsed = elapsed + GameTime.deltaTime

    local whole = math.floor(elapsed)
    if whole == shown then return end
    shown = whole

    entity.uiText.text = string.format("%02d:%02d", whole // 60, whole % 60)
end

Message that disappears

-- Scripts/UI/Message.lua (UI entity with a Text)
-- Anything can show a message with: Global.ShowMessage("Door unlocked", 3)
local timeLeft = 0

function Start()
    entity.uiText.text = ""

    Global.ShowMessage = function(message, seconds)
        entity.uiText.text = message
        timeLeft = seconds or 2
    end
end

function Update()
    if timeLeft <= 0 then return end

    timeLeft = timeLeft - GameTime.deltaTime
    if timeLeft <= 0 then entity.uiText.text = "" end
end

Show what the player is looking at

-- Scripts/UI/LookAtLabel.lua (UI entity with a Text)
public Entity player = nil
public number reach = 200

local shown = nil

function Update()
    if player == nil then return end

    local hit = player.camera:Raycast(reach, false)

    local label = ""
    if hit ~= nil and hit.entity ~= nil then label = hit.entity.name end

    if label ~= shown then
        shown = label
        entity.uiText.text = label
    end
end

More HUD scripts are in docs/scripts/14_ui.md.

Clone this wiki locally