Skip to main content

Lua Authoring Workflow

Polygon Engine exposes one case-sensitive Lua contract in editor Play Mode and on PlayStation 1. Scripts use PascalCase engine tables and methods, plus PascalCase lifecycle callbacks. A script that validates in the editor is checked against the same declared contract during a PS1 build.

Configure the Workspace

Open Project Settings > Scripting and select your external editor, then use Configure Lua Workspace. Polygon Engine creates managed files under .polygon/lua/, merges Lua workspace settings without overwriting unrelated user keys, and configures the project Assets/Scripts folder for diagnostics.

The generated files include:

  • language-server definitions for every public table, constant, method, return type, and lifecycle callback;
  • POLYGON_LUA_API.md, generated from the same declaration used by runtime parity tests;
  • an editor task that validates the PS1 scripting build path.

Generated files are derived output. Do not hand-edit them; regenerate the workspace after installing an engine update.

Create a Lua Behaviour

  1. Select a GameObject.
  2. Choose Add Component > Lua Behaviour.
  3. Select Create Script..., choose a template, and save the file under Assets/Scripts.
  4. Select Open Script to open the configured editor at that file.

The Inspector parses top-level values declared before the first function and exposes supported values as Script Properties. Use descriptive names and the gameObjectId suffix for references:

moveSpeed = 2.5
doorGameObjectId = -1
promptTextName = "Prompt Text"

function Start(gameObjectId)
Log.Print(GameObject.GetName(gameObjectId) .. " ready")
end

An Inspector override belongs to that Lua Behaviour instance. Resetting the property returns it to the default declared in the script. Prefab Sync preserves exposed Lua overrides on the instance root.

Diagnostics and Hot Reload

The Inspector validates syntax without running the script. Problems and Console messages include the script path and line when available; activating them opens the configured editor at that location. While Play Mode is running, saving a Lua file reloads its Lua Behaviour so short gameplay iterations do not require a full PS1 build.

Hot reload is an authoring convenience. Always restart Play Mode after changing initialization order, exposed properties, or persistent state, and validate the packaged CUE before treating behavior as complete.

Exact Naming Rules

Engine names are case-sensitive. For example:

function Update(gameObjectId, deltaTime)
if Input.GetButtonDown("Interact") then
AudioSource.Play(gameObjectId)
end
end

Update, Input.GetButtonDown, and AudioSource.Play are valid. Lowercase lifecycle names and undeclared global tables are not registered. Custom functions invoked by a Button, Interactable, Timeline, or GameObject.Invoke may use any valid Lua identifier, but the configured function name must match exactly.

What Runs on PS1

Lua source is not translated into C. During a PS1 build, Polygon Engine compiles each script to bytecode for a parserless, bounded Lua VM inside the native PS1 runtime. Release strips debug information; Debug preserves source line information for diagnostics. Both PS1 paths load binary bytecode, not Lua source. Build validation checks API use, script count/size, and configuration; the VM enforces heap and instruction budgets while the game executes. A static build cannot prove that every callback fits its execution budget.

Write gameplay with the hardware path in mind:

  • prefer cached GameObject and UI IDs over repeated name lookup;
  • prefer semantic Input Actions so bindings are baked into fixed records;
  • avoid creating tables or strings every frame;
  • use FixedUpdate for the bounded 30 Hz simulation step and Update for frame-driven presentation or input;
  • use Physics.Raycast, GameObject.CompareTag, and the typed component APIs for allocation-free runtime queries;
  • handle false and nil returns instead of assuming a component or asset is present.

Automated validation establishes API and budget correctness, not frame-time performance on real hardware. Profile the largest scene and run the release CUE in DuckStation and on a real console or ODE before shipping.

Continue