Editor Tools
Editor tools are Lua scripts that run in Studio while you edit a scene, not during gameplay. Use them for workflow helpers: scattering objects, batch renaming, procedural layout, validating scene setup, or any task you would otherwise do by hand in the editor.
Behaviours are the opposite: they drive runtime game logic when you press Play. They receive init, update, and the other lifecycle hooks described in Lifecycle Methods.
Both script kinds share the same property system (Properties), attach to scene objects the same way, and extend a common ScriptComponent base. The class you return from the script tells the engine which lifecycle to use.
Behaviours vs editor tools
| Behaviour | EditorTool | |
|---|---|---|
| When it runs | Play mode | Edit mode (Studio) |
| Base class | Class.new(Behaviour) |
Class.new(EditorTool) |
| Setup hook | init() |
editorInit() (optional) |
| Per-frame hooks | update, render, … |
None |
| Inspector buttons | No | Property.EditorAction |
A single scene object can have both a Behaviour and an EditorTool attached. For example, an EditorTool might scatter foliage in the editor, while a Behaviour animates that foliage at runtime.
Creating an editor tool
Create a script that returns Class.new(EditorTool) instead of Class.new(Behaviour):
local MyTool = Class.new(EditorTool)
MyTool:addProperty("runAction", Property.EditorAction, "Run action", {
info = "Execute the editor action",
})
function MyTool:runAction()
print("Action ran on", self.node:getDisplayName())
end
return MyTool
Attach the script to a scene object in the Inspector, the same way you attach a Behaviour. Configure any properties, then click the button that appears for each EditorAction field.
editorInit()
If you define editorInit, it is called once when the editor tool is loaded for that script instance in Studio (similar to init() for behaviours in play mode). Use it for one-time setup that depends on self.node or linked assets.
Editor actions
Property.EditorAction adds a button to the Inspector. The property name must match a method on your editor tool class. The default value is the button label.
MyTool:addProperty("scatter", Property.EditorAction, "Scatter objects", {
info = "Place random spheres under this node",
})
function MyTool:scatter()
-- runs when the user clicks the button
end
Important rules:
- The property name and method name must be identical (e.g. both
scatter). EditorActionproperties are UI-only. They do not store a runtime value on the instance.- Use normal properties (
Property.Number,Property.Link, …) for settings the action reads viaself.mySetting. - When a button is clicked, the engine refreshes inspector field values on the tool instance, then calls the matching method.
Property.EditorAction is intended for EditorTool scripts. Define action buttons only on editor tools, not on behaviours.
Example: random spawner
This tool spawns simple spheres as children of the node it is attached to. Adjust count and spread in the Inspector, then click Spawn spheres.
local SgSphere = require('engine/sceneobjects/sgsphere')
local Transform = require('engine/math/transform')
local Vector3 = require('engine/math/vector3')
local RandomSpawner = Class.new(EditorTool)
RandomSpawner:addProperty("count", Property.Number, 5, {
minValue = 1,
maxValue = 50,
info = "How many spheres to create",
})
RandomSpawner:addProperty("spread", Property.Number, 5, {
minValue = 0.5,
maxValue = 50,
info = "Random position radius around this node",
})
RandomSpawner:addProperty("spawn", Property.EditorAction, "Spawn spheres", {
info = "Create random spheres as children of this node",
})
function RandomSpawner:spawn()
local parent = self.node
if not parent then
return
end
for i = 1, self.count do
local x = (math.random() * 2 - 1) * self.spread
local z = (math.random() * 2 - 1) * self.spread
local y = math.random() * 0.5
SgSphere.create({
name = "Sphere " .. i,
transform = Transform.new(Vector3.new(x, y, z)),
radius = 0.2 + math.random() * 0.3,
}, parent)
end
end
return RandomSpawner
Scene changes made from an editor tool use the same scene graph APIs as runtime scripts (see Scene Graph). Consider grouping spawned objects under self.node so they stay organized in the hierarchy.
When editor tools run
- Loaded when a scene is open in Studio and the script instance is created.
- Suspended when you enter play mode (behaviours take over for runtime).
- Restored when you stop play mode.
- Not run in published builds
If a button does nothing, check the browser/console for errors. Common mistakes:
- Method name does not match the
EditorActionproperty name. - Script returns
Behaviourinstead ofEditorTool.
See also
- Properties — all property types, including
Property.EditorAction - Basics — Behaviour scripts and play-mode lifecycle
- Lifecycle Methods — runtime hooks for behaviours
- Scene Graph — creating and parenting scene objects