Scripting Runtime Reference
Polygon Engine runs precompiled Lua bytecode in a bounded parserless VM on PS1. Release strips debug information; Debug preserves source line information. The editor mirrors the public tables and lifecycle behavior for rapid iteration, while the build validates source, bytecode, API use, and configured limits.
Default Project Limits
| Setting | New-project default | Runtime boundary |
|---|---|---|
| Lua heap | 256 KB | Configurable from 64 KB to the 512 KB cap |
| Individual script | 64 KB | Hard maximum per compiled script |
| Lua Behaviours | 32 | Fixed maximum loaded in one scene |
| Instructions per callback | 50,000 | Guard checked by the VM instruction hook |
| Standard libraries | Restricted | The PS1-safe set is always enforced |
| Debug library | Off | Debug-build authoring option only |
Project Settings may lower limits to reserve memory or catch expensive scripts earlier. Raising a project value cannot exceed the runtime cap. Budget reports include Lua source/bytecode, heap, Lua Behaviour count, and exposed-property use.
Safe Script Pattern
moveSpeed = 2.5
scoreTextName = "Score Text"
local scoreTextId = -1
local score = 0
local function refresh_score()
if scoreTextId >= 0 then
Text.SetText(scoreTextId, "SCORE " .. tostring(score))
end
end
function Start(gameObjectId)
scoreTextId = UI.Find(scoreTextName)
score = PlayerPrefs.GetInt("score", 0)
refresh_score()
end
function Update(gameObjectId, deltaTime)
local moveX, moveY = Input.GetAxis("Move")
CharacterController.Move(
gameObjectId,
moveX * moveSpeed * deltaTime,
0.0,
-moveY * moveSpeed * deltaTime
)
if Input.GetButtonDown("Interact") then
score = score + 10
refresh_score()
if not PlayerPrefs.SetInt("score", score) or not PlayerPrefs.Save() then
Log.Print("Save failed: " .. SaveData.GetLastError())
end
end
end
This caches UI lookup, uses a semantic action, avoids frame-by-frame text allocation when the score is unchanged, checks persistence failures, and moves through the Character Controller.
Standard Lua Surface
The runtime includes core conversion, iteration, protected-call, metatable, and
raw-access functions, plus bounded portions of string, math, table,
coroutine, and utf8. It does not expose file, operating-system, package
loading, dynamic native modules, or a general debug environment in release PS1
builds.
Treat generated language-server definitions as the callable engine contract, not as permission to use desktop Lua facilities. Validate any standard-library function you depend on through the project's managed workspace and a PS1 build.
Performance Checklist
- Cache
GameObject.Find,UI.Find, andCanvas.Findresults inStart. - Use scalar-return APIs such as
Physics.Raycastin hot paths. - Avoid per-frame string concatenation, table construction, and full-scene name scans.
- Keep collision, UI, Timeline, and completion callbacks short.
- Split large Lua Behaviours by responsibility when their lifecycle, state, or Inspector properties no longer form one coherent component.
- Validate failure paths for missing GameObjects, components, assets, controllers, and Memory Cards.
- Measure the largest release scene on hardware; instruction and memory budgets do not prove frame time.
See Authoring Workflow and PS1 Runtime Limits.
Lua execution limits
New projects allow 256 KiB of Lua memory shared by all scripts, with a default limit of 50,000 instructions per call. Configure these values in Project Settings and keep the instruction limit positive. A limit is a safety check, not a frame-rate target: profile gameplay and keep callbacks short.
If a callback exceeds a limit, inspect the Console and reduce its work. Avoid large tables or strings at startup, cache object lookups, and spread expensive work across updates. Use a Debug build when you need source line information in a script error; use Release for the final game.
See PS1 Budget Dashboard for profiling and Lua API Reference for function arguments and return values.