Skip to main content

Lua Scripting

Glitter embeds LuaJIT as its scripting runtime, bound to C++ via sol2.
LuaJIT is a drop-in replacement for Lua 5.1 that JIT-compiles hot paths — game logic runs at near-native speed with no changes to the Lua code itself.

Scripts live under scripts://, which maps to resources/testGame/scripts/.


Entry point

The script entry point is declared in game.json:

game.json
{
"lua": {
"entry": "scripts://main.lua"
}
}

The engine loads main.lua after the scene is fully initialised.


Lifecycle callbacks

Define any or all of these global functions in main.lua:

FunctionWhen calledTypical use
on_init()Once after the scene is fully loadedSpawn creatures, subscribe to events, set up state
on_update(dt)Every frame — dt is delta time in secondsMovement, AI ticks, timers, input polling
on_shutdown()Before the scene is unloadedSave state, clean up
scripts/main.lua
-- scripts/main.lua

function on_init()
Engine.log.info("Scene ready")
end

function on_update(dt)
-- dt in seconds
end

function on_shutdown()
end

Module system

Scripts use standard Lua require. The scripts:// directory is added to package.path automatically, so modules are required by dotted path:

Module requires
local player = require("entities.player")   -- scripts/entities/player.lua
local utils = require("lib.utils") -- scripts/lib/utils.lua

scripts/
main.lua ← entry point
lib/
events.lua ← custom event helpers
utils.lua ← general utilities
entities/
player.lua ← player creature setup
guard.lua ← AI creature (CreatureBrain script)
door.lua ← non-creature interactive object
ui/
hud.lua ← HUD update logic

Coroutines for timed sequences

LuaJIT coroutines let you write time-based sequences without blocking the game loop. Use Engine.coroutine.start to register a function as a managed coroutine, and Engine.coroutine.wait to sleep inside it:

scripts/main.lua
function on_init()
Engine.coroutine.start(opening_cutscene)
end

function opening_cutscene()
local cam = Engine.scene.find("mainCamera")
cam:set_position(0.0, 5.0, 10.0)

Engine.coroutine.wait(2.0) -- yields for 2 seconds, frame loop continues

cam:set_position(0.0, 2.0, 0.0)
Engine.coroutine.wait(1.0)

Engine.events.fire("cutscene_done")
end

Editor support — LuaLS type bindings

The file scripts/types/engine_api.lua contains full ---@class / ---@param / ---@return annotations for the entire Engine API.
Open the scripts/ folder in VS Code with the Lua Language Server extension installed and you get autocomplete, type errors, and hover docs for every Engine call.


Further reading