7.4 KiB
Database Data Structure
This document describes the JSON format saved to and loaded from the database.
Top-level: RoomExport
{
"guid": "string",
"skybox": "string | null",
"sky-color": "#rrggbb",
"jsonversion": 2.0,
"items": [ ...RoomItem ],
"groups": { ...SceneGroups },
"background_sound": "string | null"
}
| Field | Type | Description |
|---|---|---|
guid |
string |
Unique room identifier |
skybox |
string | null |
Skybox asset path (currently unused) |
sky-color |
string |
Background hex color |
jsonversion |
number |
Schema version (2.0) |
items |
RoomItem[] |
All objects in the room |
groups |
SceneGroups (optional) |
Item/group hierarchy created via the Grouping feature. Omitted entirely when there are no groups |
background_sound |
string | null (optional) |
Storage path of the uploaded ambient sound file, set from World Settings → Sound |
RoomItem
Every item in the items array shares this base shape:
{
"id": 0,
"position": { "x": 0.0, "y": 0.0, "z": 0.0 },
"rotation": { "x": 0.0, "y": 0.0, "z": 0.0 },
"scale": { "x": 1.0, "y": 1.0, "z": 1.0 },
"type": "pre-defined | user-defined",
"resourcename": "string",
"item-custom-args": [ ...ItemArg ],
"item-custom-args-adv": null
}
Coordinate system note: The X-axis is flipped on save (
x=-creator_x) and un-flipped on load. Y-axis rotation is also negated.
id: Stable numeric identifier assigned when the item is created in the Creator (the key of the in-memorySceneItemsrecord). It is preserved across save/load rather than derived from array position, so group membership and block-coding references (sourceItemId/targetItemId) keep pointing at the right item even after items are added or removed. Rooms saved before this field existed fall back to array index on load.
ItemArg
{ "argument": "key", "value": "value_as_string" }
All values are serialized as strings.
SceneGroups
Top-level groups field grouping items (and other groups) so they can be selected/moved together in the Creator. Keyed by numeric group ID, parallel to items being keyed by item ID.
{
"1": {
"name": "Group 1",
"children": [
{ "kind": "item", "id": 4 },
{ "kind": "item", "id": 7 },
{ "kind": "group", "id": 2 }
]
}
}
| Field | Type | Description |
|---|---|---|
name |
string |
Display name, editable in the Item List |
children |
GroupChild[] |
Members of the group — either an item ({ "kind": "item", "id": <RoomItem.id> }) or a nested group ({ "kind": "group", "id": <group id> }) |
Group membership references stable RoomItem.ids (see the id note above), so groups keep pointing at the right items across save/load. The groups field is omitted from the export entirely when the room has no groups.
Per-type resourcename and custom args
Basic shapes
| Creator type | resourcename |
Custom args |
|---|---|---|
Cube |
Cube |
color |
Sphere |
Sphere |
color |
Cylinder |
Cylinder |
color |
Cone |
Cone |
color |
Floor |
Plane |
color, opacity |
Wall |
Wall |
color, opacity |
Lights
| Creator type | resourcename |
Custom args |
|---|---|---|
Directional Light |
Directional Light |
color, intensity†, target ("x,y,z") |
Point Light |
Point Light |
color, intensity† |
†
intensityis the key saved in the database, but Unity readsbrightness— the args will not apply at runtime until this mismatch is resolved. See individual object docs.
Room access
| Creator type | resourcename |
Custom args |
|---|---|---|
Entrance |
Entrance |
(none) |
GoToOtherRoom |
GoToOtherRoom |
RoomName, UUID, color (❌ not yet implemented in Creator or Unity) |
Streaming / media
| Creator type | resourcename |
Custom args |
|---|---|---|
Billboard |
Billboard |
url (Supabase storage path, signed at runtime) |
LiveKitStream |
LiveKitStream |
LiveKitRoomID, shader, GreenScreenColor, GreenScreenBorderSettings, GreenScreenColorNear, widthcrop, heightcrop |
VideoWall |
VideoWall |
file, shader, volume, controls, autoplay, widthcrop, heightcrop |
Presentation |
PresentationWall |
file, widthcrop, heightcrop, controls (❌ not in Creator) |
Camera |
CCTVCamera |
target ("x,y,z"), fov (derived: zoom * 60) |
Logic
| Creator type | resourcename |
Custom args |
|---|---|---|
Area |
Area |
color, opacity (serialized but not user-editable; the area is always rendered as an orange glow in the editor) |
The Area Collider is an editor-only helper zone with no Unity-side visual — its footprint is defined by
scale.x/scale.z. It is picked as thesourceItemIdof an"in_area"Block Coding trigger (see Block Coding data structure).
Other / Props
| Creator type | resourcename |
type field |
Custom args |
|---|---|---|---|
Text |
Text |
pre-defined |
text, color, fontSize, fontWeight |
Whiteboard |
WhiteboardWall |
pre-defined |
(none — not serialized by Creator) |
Custom |
(asset filename) | user-defined |
file, color, material |
material values (Custom, Speaker)
| Value | Shader |
|---|---|
0 |
Metallic |
1 |
Unlit |
2 |
Specular |
3 |
FakeEmission |
Common optional arg (all types)
| Arg | Type | Description |
|---|---|---|
grabable |
"true" | "false" |
Whether the item can be grabbed in-experience |
locked |
"true" | "false" |
Whether the item is locked against moving/deleting in the Creator. Editor-only concern — Unity/runtime does not read this arg |
grabableandlockedare both written by the sharedbuildCustomArgs()helper, so they are present on every type exceptText,Billboard, andEntrance, which build theiritem-custom-argsarray by hand and currently omit both.
Example — Directional Light
{
"id": 0,
"position": { "x": 0, "y": 5, "z": 0 },
"rotation": { "x": 0, "y": 0, "z": 0 },
"scale": { "x": 1, "y": 1, "z": 1 },
"type": "pre-defined",
"resourcename": "Directional Light",
"item-custom-args": [
{ "argument": "color", "value": "#ffffff" },
{ "argument": "intensity", "value": "20" },
{ "argument": "target", "value": "0,0,0" }
],
"item-custom-args-adv": null
}
Example — CCTV Camera
{
"id": 1,
"position": { "x": 0, "y": 4, "z": 0 },
"rotation": { "x": 0, "y": 0, "z": 0 },
"scale": { "x": 1, "y": 1, "z": 1 },
"type": "pre-defined",
"resourcename": "CCTVCamera",
"item-custom-args": [
{ "argument": "target", "value": "0,0,0" },
{ "argument": "fov", "value": "60" }
],
"item-custom-args-adv": null
}
Example — Custom (user-uploaded GLB)
{
"id": 2,
"position": { "x": -4.0, "y": 1.0, "z": 0.0 },
"rotation": { "x": 0.0, "y": 0.0, "z": 0.0 },
"scale": { "x": 1.0, "y": 1.0, "z": 1.0 },
"type": "user-defined",
"resourcename": "b83a17ab-92bf-4122-a4d0-7b467a105ae0/podest.glb",
"item-custom-args": [
{ "argument": "file", "value": "b83a17ab-92bf-4122-a4d0-7b467a105ae0/podest.glb" },
{ "argument": "color", "value": "#ffffff" },
{ "argument": "material", "value": "0" }
],
"item-custom-args-adv": null
}