Your first script
This page walks you through running a script from an empty editor to a working overlay, and shows what the console tells you when something goes wrong.
Step 1: write the script
Open the Lua tab and paste this script.
local paint = xiao.paint
local red = paint.color.rgb(255, 0, 0)
local white = paint.color.rgb(255, 255, 255)
local black = paint.color.rgb(0, 0, 0)
print("script started")
paint.listener.add("hello", function(width, height)
local center = paint.point.vector2(width / 2, height / 2)
paint.circle.filled(center, red, 60)
paint.text.center(paint.point.vector2(width / 2, height / 2 - 8), "hello", white, black)
end)
Step 2: press Execute
- The editor text is executed as is. You do not need to save it first.
- The console window opens over the game and shows
script started. - A red circle with the word
helloappears in the middle of the screen.
The paint listener is called again on every frame with the screen size, which is why the circle stays on screen. A shape is only drawn for one frame, see Draw an overlay and xiao.paint.
Step 3: change it while it runs
Edit the script, for example change "hello" to "hello again", and press Execute again.
-
The new code runs in the same VM.
-
Listeners are keyed by an id. Adding
"hello"a second time replaces the first callback, so you see one circle with the new text. -
If you had used a different id, both listeners would draw and you would see two overlapping circles.
Everything a previous execution created stays alive: globals, listeners, receivers, hooks, timers and signals. Use stable ids so that re-executing replaces your callbacks instead of stacking them.
Step 4: read an error
Replace the listener with one that calls a function that does not exist (circle.fill instead of circle.filled):
xiao.paint.add("hello", function(width, height)
xiao.paint.circle.fill(xiao.paint.point.vector2(100, 100), xiao.paint.color.rgb(255, 0, 0), 20)
end)
The console shows, in red, paint listener 'hello' removed: followed by the error with the file name, the line and a
stack traceback. The listener is removed and the rest of the VM keeps running: fix the call (circle.filled) and press
Execute again.
An error in the top level of the script (the main chunk) fails the execution, prints the error, and leaves the VM running.
Step 5: clear the VM
Press Clear VM.
-
on_unloadand theunloadsignal run, so a script can save its state, then the xiao.workspace tables are written. -
The VM is destroyed: every global, paint listener, receiver, hook, timer, signal, image and packet block of every execution is gone. The console prints
vm cleared. -
The circle disappears. The next Execute starts from a fresh VM.
Next steps
- Running scripts: editor shortcuts, console, time limits, lifecycle, order of a frame.
- Sandbox: what a script can and cannot touch.
- Draw an overlay: build a real HUD.
- React to events: chat, entities, damage and timers.
- Read the player and the world: health, items and blocks.