Skip to main content
The Dialog namespace gives you three distinct ways to present text to the player during a level: messages that require a button press to dismiss, messages that disappear on their own after a fixed duration, and messages whose entire lifecycle your script controls manually. Choosing the right type makes your level feel polished and purposeful.

Message Types at a Glance

TypeHow it closesBest for
CloseablePlayer presses a buttonTutorial instructions, important alerts
TemporaryAuto-dismisses after N secondsHints, countdown warnings, short feedback
ManualYour script calls destroyManualStory dialog, scripted narrative sequences

Closeable Messages

A closeable message blocks the player’s attention until they actively dismiss it. Use this whenever the player must read a message before continuing.

Signatures

-- Create with default black background
function Dialog.createCloseable(message: string): any

-- Create with a custom background color
function Dialog.createCloseable(message: string, backgroundColor: Color): any

-- Re-open a message stored by ID (default black background)
function Dialog.openCloseable(messageId: string): any

-- Re-open a message stored by ID with a custom background color
function Dialog.openCloseable(messageId: string, backgroundColor: Color): any
Dialog.createCloseable displays the message immediately. Dialog.openCloseable is used to re-show a previously created message using the ID returned from creation.

Example — Tutorial at Level Start

Attach this script to the Level entity. The OnStart hook fires as soon as the level loads.
function OnStart(self)
    -- Warm amber background to match the tutorial theme
    local bgColor = Color.new(0.6, 0.3, 0.0, 0.85)

    Dialog.createCloseable(
        "Roll onto every key to unlock the exit!\nAvoid the red spikes or you'll lose a life.",
        bgColor
    )
end
Keep closeable messages short — one or two sentences. If you need to show a series of instructions, chain multiple calls inside Level.delayAction to space them out.

Temporary Messages

A temporary message shows itself and then automatically vanishes after the number of seconds you specify. The player never needs to interact with it.

Signatures

-- Create and show immediately (default black background)
function Dialog.createTemporary(message: string, duration: number): any

-- Create and show with a custom background color
function Dialog.createTemporary(message: string, duration: number, backgroundColor: Color): any

-- Re-open a stored message by ID
function Dialog.openTemporary(messageId: string, duration: number): any

-- Re-open a stored message by ID with a custom background color
function Dialog.openTemporary(messageId: string, duration: number, backgroundColor: Color): any
The duration parameter is measured in seconds.

Example — Countdown Warning

This script runs in the Level OnUpdate hook and shows a warning when the hourglass drops below 15 seconds.
local warningSent = false

function OnUpdate(self, deltaTime)
    if not warningSent and Level.isHourglassEnabled and Level.remainingTime <= 15.0 then
        warningSent = true

        local urgentColor = Color.new(0.8, 0.1, 0.0, 0.9) -- deep red
        Dialog.createTemporary("Hurry! Less than 15 seconds remain!", 4.0, urgentColor)
    end
end
The warningSent guard prevents the message from re-firing every frame once the threshold is crossed. Always use a flag like this with OnUpdate.

Manual Messages

Manual messages give you complete control. You create the dialog with an ID, open and close it whenever you like, and destroy it when you no longer need it.

Signatures

-- Create (does not show yet)
function Dialog.createManual(dialogId: string, message: string): any
function Dialog.createManual(dialogId: string, message: string, backgroundColor: Color): any

-- Show a previously created manual message
function Dialog.openManual(dialogId: string, messageId: string): any
function Dialog.openManual(dialogId: string, messageId: string, backgroundColor: Color): any

-- Check whether a manual dialog still exists
function Dialog.existsManual(dialogId: string): boolean

-- Remove the dialog entirely
function Dialog.destroyManual(dialogId: string): any
The dialogId is a unique string key that identifies this dialog in your script. The messageId is the identifier of the specific message content to display inside it.

Example — Scripted Story Dialog Sequence

This script is attached to a Block entity. When the ball rolls onto the block (OnBallRoll with rollIn = true), it kicks off a three-part dialog sequence using Level.delayAction to pace the lines.
local storyTriggered = false

function OnBallRoll(self, rollIn, side, ball)
    if not rollIn or storyTriggered then
        return
    end
    storyTriggered = true

    local storyColor = Color.new(0.05, 0.05, 0.2, 0.92) -- dark navy

    -- Show the first line immediately
    Dialog.createManual("story_dialog", "The ancient gate stirs...", storyColor)
    Dialog.openManual("story_dialog", "story_dialog")

    -- Replace the message after 3 seconds
    Level.delayAction(3.0, function()
        if Dialog.existsManual("story_dialog") then
            Dialog.destroyManual("story_dialog")
        end
        Dialog.createManual("story_dialog", "Only the one who carries all keys may pass.", storyColor)
        Dialog.openManual("story_dialog", "story_dialog")
    end)

    -- Dismiss after another 4 seconds
    Level.delayAction(7.0, function()
        if Dialog.existsManual("story_dialog") then
            Dialog.destroyManual("story_dialog")
        end
    end)
end
Always call Dialog.existsManual before Dialog.destroyManual. If the dialog has already been cleaned up (for example, by a restart), calling destroy on a non-existent ID will produce an error.

Customising Background Colors

Every create* and open* function accepts an optional Color as its last argument. Colors are RGBA values in the 0.01.0 range.
-- Using a named preset
local bg = Color.red

-- Using an RGB value (fully opaque)
local bg = Color.new(0.1, 0.4, 0.8)

-- Using RGBA (semi-transparent dark teal)
local bg = Color.new(0.0, 0.3, 0.3, 0.8)
When you omit the color argument, the game uses a solid black background.
A semi-transparent background (alpha around 0.8) lets the player see the level behind the dialog, which feels less intrusive for short temporary messages.