Advanced Features
This guide covers advanced scene features including skyboxes, spawn points, movement bounds, gamemodes, autosave, trigger volumes, and teleport volumes.
Skybox
Skyboxes provide environment mapping for the scene background.
"skybox": {
"uri": "https://example.com/skybox.jpg",
"rotation": {"x": 0.0, "y": 0.0, "z": 0.0}
}
Properties — specify exactly one of:
uri(string): equirectangular sky — LDR (.png/.jpg/.jpeg/.tga) or Radiance.hdr(HTTPS, or Allow HTTP for travel testing)faces(object): six-face cubemap withpx,nx,py,ny,pz,nzHTTPS URIs (all LDR or all.hdr)rotation(vec3, optional): Rotation in degrees
EXR is not supported.
Use cases: Sky, space, indoor environments, atmosphere
Spawn Points
Spawn points define where players appear when entering the scene.
"spawn": {"x": 0.0, "y": 1.0, "z": 0.0}
Default: (0, 0, 0) if not specified
Use cases:
- Start locations
- Respawn points
- Scene entry points
Movement Bounds
Movement bounds limit player movement to a specific area.
"movementBounds": {
"min": {"x": -50.0, "y": 0.0, "z": -50.0},
"max": {"x": 50.0, "y": 100.0, "z": 50.0}
}
Properties:
min(vec3, required): Minimum bounds (X, Y, Z)max(vec3, required): Maximum bounds (X, Y, Z)
Default when omitted: movement is still clamped to approximately ±100 on each axis
(min = (-100, -100, -100), max = (100, 100, 100)). Large open worlds must set
explicit movementBounds or players hit an invisible wall at ±100.
Use cases:
- Confined spaces
- Level boundaries
- Preventing players from leaving the play area
Gamemode Scripts
Gamemode scripts provide scene-wide logic and state management.
"gamemode": {
"file": "gamemode-script"
}
Properties:
file(string, required): Asset ID of the gamemode script
Features:
- Scene-wide state management
- Event system
- Save/load support
- Persistent data via localStorage
See Lua/Luau API - Gamemode for details.
Autosave Volumes
Autosave volumes automatically save game state when the player enters.
{
"id": "autosave-zone",
"type": "autosaveVolume",
"position": {"x": 0.0, "y": 0.0, "z": 0.0},
"rotation": {"x": 0.0, "y": 0.0, "z": 0.0},
"scale": {"x": 5.0, "y": 5.0, "z": 5.0},
"autosaveVolume": {}
}
Behavior:
- Triggers when player enters the volume
- Saves gamemode state and script state
- Can show notification (configured via
autosaveNotification)
Use cases: Checkpoints, safe zones, progress saving
Autosave Notifications
Configure on-screen notifications when autosave occurs.
"autosaveNotification": {
"text": "Game saved!",
"x": 0.02,
"y": 0.95,
"font": "default-font",
"color": {"x": 1.0, "y": 1.0, "z": 1.0}
}
Properties:
text(string, optional): Notification textx/y(number, optional): Screen position (0–1 normalized)- X: 0 = left, 1 = right
- Y: 0 = bottom, 1 = top
font(string, optional): Font asset IDcolor(vec3, optional): Text color (RGB, 0-1)
Trigger Volumes
Trigger volumes detect player presence and fire author-chosen gamemode event names via Gamemode.onEvent(eventName, data). Most volume types require an eventName string in their typed properties object (not a synthetic volume_* name).
Look At Volume (type: "lookAtVolume")
Fires when the player looks toward the volume (outside it).
{
"id": "look-trigger",
"type": "lookAtVolume",
"position": {"x": 0.0, "y": 0.0, "z": 0.0},
"rotation": {"x": 0.0, "y": 0.0, "z": 0.0},
"scale": {"x": 2.0, "y": 2.0, "z": 2.0},
"lookAtVolume": {
"eventName": "looked_at_sign",
"singleUse": false,
"cooldownSeconds": 0,
"fovDegrees": 30
}
}
Properties: eventName (required); optional singleUse, cooldownSeconds, fovDegrees
Looked At Volume (type: "lookedAtVolume")
Fires when the player is inside the volume and looks at a target instance.
{
"id": "looked-trigger",
"type": "lookedAtVolume",
"position": {"x": 0.0, "y": 0.0, "z": 0.0},
"rotation": {"x": 0.0, "y": 0.0, "z": 0.0},
"scale": {"x": 2.0, "y": 2.0, "z": 2.0},
"lookedAtVolume": {
"eventName": "looked_at_npc",
"targetInstanceId": "npc-1",
"fovDegrees": 30
}
}
Properties: eventName, targetInstanceId (required); optional singleUse, cooldownSeconds, fovDegrees
Single Trigger Volume (type: "singleTriggerVolume")
Fires once on enter.
{
"id": "single-trigger",
"type": "singleTriggerVolume",
"position": {"x": 0.0, "y": 0.0, "z": 0.0},
"rotation": {"x": 0.0, "y": 0.0, "z": 0.0},
"scale": {"x": 2.0, "y": 2.0, "z": 2.0},
"singleTriggerVolume": {
"eventName": "checkpoint_reached"
}
}
Multi Trigger Volume (type: "multiTriggerVolume")
Fires every enter (optionally capped).
{
"id": "multi-trigger",
"type": "multiTriggerVolume",
"position": {"x": 0.0, "y": 0.0, "z": 0.0},
"rotation": {"x": 0.0, "y": 0.0, "z": 0.0},
"scale": {"x": 2.0, "y": 2.0, "z": 2.0},
"multiTriggerVolume": {
"eventName": "zone_entered",
"maxFires": 0,
"autoRemoveOnFire": false
}
}
Cooldown Trigger Volume (type: "cooldownTriggerVolume")
Fires on enter with a cooldown between fires.
{
"id": "cooldown-trigger",
"type": "cooldownTriggerVolume",
"position": {"x": 0.0, "y": 0.0, "z": 0.0},
"rotation": {"x": 0.0, "y": 0.0, "z": 0.0},
"scale": {"x": 2.0, "y": 2.0, "z": 2.0},
"cooldownTriggerVolume": {
"eventName": "pickup_pulse",
"cooldownSeconds": 5.0,
"maxFires": 0
}
}
Properties: eventName, cooldownSeconds (required); optional maxFires
Exit Trigger Volume (type: "exitTriggerVolume")
Fires when the player exits the volume.
{
"id": "exit-trigger",
"type": "exitTriggerVolume",
"position": {"x": 0.0, "y": 0.0, "z": 0.0},
"rotation": {"x": 0.0, "y": 0.0, "z": 0.0},
"scale": {"x": 2.0, "y": 2.0, "z": 2.0},
"exitTriggerVolume": {
"eventName": "left_safe_zone"
}
}
Stay Trigger Volume (type: "stayTriggerVolume")
Fires repeatedly while the player remains inside.
{
"id": "stay-trigger",
"type": "stayTriggerVolume",
"position": {"x": 0.0, "y": 0.0, "z": 0.0},
"rotation": {"x": 0.0, "y": 0.0, "z": 0.0},
"scale": {"x": 2.0, "y": 2.0, "z": 2.0},
"stayTriggerVolume": {
"eventName": "healing_tick",
"stayInterval": 1.0
}
}
Properties: eventName, stayInterval (required)
Timed Entry Trigger Volume (type: "timedEntryTriggerVolume")
Fires after the player has stayed inside for a duration.
{
"id": "timed-trigger",
"type": "timedEntryTriggerVolume",
"position": {"x": 0.0, "y": 0.0, "z": 0.0},
"rotation": {"x": 0.0, "y": 0.0, "z": 0.0},
"scale": {"x": 2.0, "y": 2.0, "z": 2.0},
"timedEntryTriggerVolume": {
"eventName": "channel_complete",
"requiredStayTime": 3.0
}
}
Properties: eventName, requiredStayTime (required)
Counter Trigger Volume (type: "counterTriggerVolume")
Shares a named counter (counter_word) across volumes; increments on enter. Schema fields are counter_word / required_count only (no author eventName today).
{
"id": "counter-trigger",
"type": "counterTriggerVolume",
"position": {"x": 0.0, "y": 0.0, "z": 0.0},
"rotation": {"x": 0.0, "y": 0.0, "z": 0.0},
"scale": {"x": 2.0, "y": 2.0, "z": 2.0},
"counterTriggerVolume": {
"counter_word": "switches",
"required_count": 5,
"auto_reset_after_fire": false,
"fire_once_when_reached": false
}
}
Properties: counter_word, required_count (required); optional auto_reset_after_fire, fire_once_when_reached
Sequence Trigger Volume (type: "sequenceTriggerVolume")
Volumes in the same sequence_group_id must be entered in ascending sequence_index order. Optional eventName is the completion event (fires once when the highest index in the group is completed correctly).
{
"id": "sequence-step-0",
"type": "sequenceTriggerVolume",
"position": {"x": 0.0, "y": 0.0, "z": 0.0},
"rotation": {"x": 0.0, "y": 0.0, "z": 0.0},
"scale": {"x": 2.0, "y": 2.0, "z": 2.0},
"sequenceTriggerVolume": {
"sequence_group_id": "puzzle_a",
"sequence_index": 0,
"reset_if_wrong": true,
"eventName": "puzzle_a_complete"
}
}
Properties:
sequence_group_id(string, required)sequence_index(integer, required, 0-based)reset_if_wrong(boolean, optional)eventName(string, optional): Completion gamemode event
Toggle Trigger Volume (type: "toggleTriggerVolume")
Toggles on/off each enter; fires on_activate_event / on_deactivate_event when set.
{
"id": "toggle-trigger",
"type": "toggleTriggerVolume",
"position": {"x": 0.0, "y": 0.0, "z": 0.0},
"rotation": {"x": 0.0, "y": 0.0, "z": 0.0},
"scale": {"x": 2.0, "y": 2.0, "z": 2.0},
"toggleTriggerVolume": {
"is_on": false,
"on_activate_event": "gate_open",
"on_deactivate_event": "gate_close"
}
}
Teleport Volumes
Teleport volumes instantly move the player to a new position. On activation they also fire the fixed gamemode event teleport_volume_activated.
{
"id": "teleporter",
"type": "teleportVolume",
"position": {"x": 0.0, "y": 0.0, "z": 0.0},
"rotation": {"x": 0.0, "y": 0.0, "z": 0.0},
"scale": {"x": 2.0, "y": 2.0, "z": 2.0},
"teleportVolume": {
"destination": {"x": 10.0, "y": 5.0, "z": 10.0}
}
}
Properties:
destination(vec3, required): Target position
Use cases: Elevators, fast travel, level transitions
Interaction Volumes
Interaction volumes fire when the player is inside and presses a bound action. The action field is matched case-insensitively against runtime action names (interact, jump, etc.).
{
"id": "interaction-zone",
"type": "interactionVolume",
"position": {"x": 0.0, "y": 0.0, "z": 0.0},
"rotation": {"x": 0.0, "y": 0.0, "z": 0.0},
"scale": {"x": 2.0, "y": 2.0, "z": 2.0},
"interactionVolume": {
"eventName": "zone_used",
"action": "interact"
}
}
Properties: eventName, action (required)
Volume Size
All volumes use the scale property to define their size:
- Scale X: Width
- Scale Y: Height
- Scale Z: Depth
The volume is a box centered at the position, with dimensions determined by scale.
Trigger Events
When a volume fires, the runtime calls Gamemode.triggerEvent / listeners registered with Gamemode.onEvent using the author-supplied eventName (or toggle activate/deactivate names, or sequence completion eventName). Payload typically includes instanceId and a reason string (for example enter, exit, stay, interaction).
There is no automatic volume_<type>_<instanceId> event name pattern.
Handle events in gamemode scripts:
Gamemode.onEvent("zone_used", function(data)
print("Used zone", data.instanceId)
end)
Best Practices
- Size volumes appropriately: Not too small (hard to trigger) or too large (triggers unexpectedly)
- Use appropriate trigger types: Choose the right volume type for your use case
- Test trigger behavior: Verify volumes work as expected
- Combine with scripts: Use volumes to trigger script behaviors
- Organize with worlds: Use world IDs to group related scenes
Next Steps
- Lua/Luau API - Learn to script volume behaviors
- Examples - See advanced features in action
- Scene Format Intro - Return to scene format overview