2D scene format
VGAI Reference 0.3
Planned versioned generated-schema truth covering First-party PixiJS worlds and 2D authoring.
planned · generated · immutable Reference 0.3
Lifecycle and constraints
Detailed constraints will publish with the generated or reviewed entry.
Runnable Learn material
Generated format inventory
Inventory only — AC-REF-002 is not passed. Valid parser-verified examples, narrative guidance, complete cross-field/runtime constraints, and version history remain deferred. This page must not be treated as a complete format contract.
Source: packages/engine/schemas/scn2d.schema.json ·
101 branch-sensitive field records ·
63 source-described.
This source intentionally supersedes the frozen study boundary.
scene-2d · file · 101 fields
| Field / branch | Type | Required | Default | Constraints | Description |
|---|---|---|---|---|---|
# $ | object | yes | none | {"additionalProperties":false} | A world2d scene (PixiJS render surface) |
# $.version | number | no | none | none | Scene format version |
# $.name | string | no | none | none | Scene name shown in the native 2D document hierarchy and inspector |
# $.surface | const "world2d" | no | none | {"const":"world2d"} | Render surface. Always 'world2d' |
# $.gravity | array | no | none | none | World gravity [x, y] in px/s^2. Default [0, 9.8 * pixelsPerMeter] ([0, 980] at the default scale) |
# $.gravity[0] | number | yes | none | none | Missing source description |
# $.gravity[1] | number | yes | none | none | Missing source description |
# $.pixelsPerMeter | number | no | none | {"exclusiveMinimum":0} | Authored pixels per physics meter. Configures native Rapier World.lengthUnit and scales default gravity. Default 100 |
# $.background | string | no | none | none | Background color hex string. Default '#10101a' |
# $.entities | array | yes | none | none | Root entities of the world2d scene |
# $.entities[] | ref #/$defs/__schema0 | yes | none | none | Missing source description |
# $.entities[]ref:#/$defs/__schema0 | object | yes | none | {"additionalProperties":false} | Missing source description |
# $.entities[].idref:#/$defs/__schema0 | string | no | none | none | Unique entity ID. Auto-generated if omitted |
# $.entities[].nameref:#/$defs/__schema0 | string | yes | none | none | Human-readable entity name (shown in hierarchy panel) |
# $.entities[].surfaceref:#/$defs/__schema0 | enum (2) | no | none | {"enum":["world2d","world3d"]} | Render surface that instantiates this entity. Default 'world2d' in a Scene2D file. The 'world3d' value is REJECTED at parse (T4.1): declared but has no runtime reader — authoring surface: 'world3d' throws. Do not author it ('world2d', the default, is fine). |
# $.entities[].visibleref:#/$defs/__schema0 | boolean | no | none | none | Whether the entity and its children are rendered |
# $.entities[].lockedref:#/$defs/__schema0 | boolean | no | none | none | Prevent selection and editing in the native 2D scene editor |
# $.entities[].tagsref:#/$defs/__schema0 | array | no | none | none | Arbitrary string tags for runtime queries. REJECTED at parse (T4.1): declared but has no runtime reader — authoring this field throws. Do not author. |
# $.entities[].tags[]ref:#/$defs/__schema0 | string | yes | none | none | Missing source description |
# $.entities[].transform2dref:#/$defs/__schema0 | object | no | none | {"additionalProperties":false} | Local 2D transform relative to parent |
# $.entities[].transform2d.positionref:#/$defs/__schema0 | array | no | none | none | Local position [x, y] in world2d pixels |
# $.entities[].transform2d.position[0]ref:#/$defs/__schema0 | number | yes | none | none | Missing source description |
# $.entities[].transform2d.position[1]ref:#/$defs/__schema0 | number | yes | none | none | Missing source description |
# $.entities[].transform2d.rotationref:#/$defs/__schema0 | number | no | none | none | Rotation in radians about the Z axis. Default 0 |
# $.entities[].transform2d.scaleref:#/$defs/__schema0 | array | no | none | none | Scale per axis [x, y]. Default [1, 1] |
# $.entities[].transform2d.scale[0]ref:#/$defs/__schema0 | number | yes | none | none | Missing source description |
# $.entities[].transform2d.scale[1]ref:#/$defs/__schema0 | number | yes | none | none | Missing source description |
# $.entities[].transform2d.pivotref:#/$defs/__schema0 | array | no | none | none | Local pivot point [x, y] (center of rotation/scale) |
# $.entities[].transform2d.pivot[0]ref:#/$defs/__schema0 | number | yes | none | none | Missing source description |
# $.entities[].transform2d.pivot[1]ref:#/$defs/__schema0 | number | yes | none | none | Missing source description |
# $.entities[].pivotref:#/$defs/__schema0 | array | no | none | none | Local-space pivot point [x, y] |
# $.entities[].pivot[0]ref:#/$defs/__schema0 | number | yes | none | none | Missing source description |
# $.entities[].pivot[1]ref:#/$defs/__schema0 | number | yes | none | none | Missing source description |
# $.entities[].spriteref:#/$defs/__schema0 | object | no | none | {"additionalProperties":false} | 2D sprite appearance |
# $.entities[].sprite.textureref:#/$defs/__schema0 | string | no | none | none | Texture asset URL (loaded via PIXI.Assets). Omit for a tintable 1x1 white texture |
# $.entities[].sprite.frameref:#/$defs/__schema0 | string | no | none | {"minLength":1} | Spritesheet frame/sub-texture name when `texture` is a spritesheet atlas |
# $.entities[].sprite.animationref:#/$defs/__schema0 | string | no | none | {"minLength":1} | Named spritesheet animation from `texture` (PIXI.Spritesheet.animations); mutually exclusive with `frame` |
# $.entities[].sprite.anchorref:#/$defs/__schema0 | array | no | none | none | Normalized anchor [x, y] (0..1). Default [0.5, 0.5] |
# $.entities[].sprite.anchor[0]ref:#/$defs/__schema0 | number | yes | none | none | Missing source description |
# $.entities[].sprite.anchor[1]ref:#/$defs/__schema0 | number | yes | none | none | Missing source description |
# $.entities[].sprite.tintref:#/$defs/__schema0 | string | no | none | none | Tint color as hex string (e.g. '#ff8800'). Default white |
# $.entities[].sprite.alpharef:#/$defs/__schema0 | number | no | none | {"minimum":0,"maximum":1} | Opacity 0..1. Default 1 |
# $.entities[].sprite.widthref:#/$defs/__schema0 | number | no | none | none | Explicit display width in pixels (overrides texture size) |
# $.entities[].sprite.heightref:#/$defs/__schema0 | number | no | none | none | Explicit display height in pixels (overrides texture size) |
# $.entities[].sprite.blendModeref:#/$defs/__schema0 | enum (4) | no | none | {"enum":["normal","add","multiply","screen"]} | PixiJS blend mode. Default normal |
# $.entities[].sprite.interactiveref:#/$defs/__schema0 | boolean | no | none | none | Enable federated pointer events (eventMode=static) so this sprite can be picked |
# $.entities[].sprite.filterref:#/$defs/__schema0 | enum (3) | no | none | {"enum":["none","blur","desaturate"]} | Apply a PixiJS filter (BlurFilter / ColorMatrix desaturate). Default none |
# $.entities[].sprite.fpsref:#/$defs/__schema0 | number | no | none | {"exclusiveMinimum":0} | AnimatedSprite playback speed in frames/sec. Default 8 |
# $.entities[].sprite.loopref:#/$defs/__schema0 | boolean | no | none | none | Whether the named spritesheet animation loops. Default true |
# $.entities[].textref:#/$defs/__schema0 | object | no | none | {"additionalProperties":false} | World-space text label |
# $.entities[].text.textref:#/$defs/__schema0 | string | yes | none | none | The string to display |
# $.entities[].text.fontSizeref:#/$defs/__schema0 | number | no | none | none | Font size in pixels. Default 24 |
# $.entities[].text.fillref:#/$defs/__schema0 | string | no | none | none | Text color as hex string. Default '#ffffff' |
# $.entities[].text.anchorref:#/$defs/__schema0 | array | no | none | none | Normalized anchor [x, y] (0..1). Default [0.5, 0.5] |
# $.entities[].text.anchor[0]ref:#/$defs/__schema0 | number | yes | none | none | Missing source description |
# $.entities[].text.anchor[1]ref:#/$defs/__schema0 | number | yes | none | none | Missing source description |
# $.entities[].tilemapref:#/$defs/__schema0 | object | no | none | {"additionalProperties":false} | 2D tilemap (CompositeTilemap) |
# $.entities[].tilemap.framesref:#/$defs/__schema0 | array | yes | none | {"minItems":1} | Ordered Pixi spritesheet frame names used as tile indices |
# $.entities[].tilemap.frames[]ref:#/$defs/__schema0 | string | yes | none | {"minLength":1} | Missing source description |
# $.entities[].tilemap.textureref:#/$defs/__schema0 | string | yes | none | {"minLength":1} | URL or project path to a Pixi spritesheet JSON asset |
# $.entities[].tilemap.tileSizeref:#/$defs/__schema0 | number | yes | none | {"exclusiveMinimum":0} | Positive square tile width/height in pixels |
# $.entities[].tilemap.tilesref:#/$defs/__schema0 | array | yes | none | none | Row-major grid of frame indices; -1 is an empty cell (each row is an array of tile indices) |
# $.entities[].tilemap.tiles[]ref:#/$defs/__schema0 | array | yes | none | none | Missing source description |
# $.entities[].tilemap.tiles[][]ref:#/$defs/__schema0 | integer | yes | none | {"minimum":-9007199254740991,"maximum":9007199254740991} | Missing source description |
# $.entities[].physics2dref:#/$defs/__schema0 | object | no | none | {"additionalProperties":false} | 2D physics rigid body + collider |
# $.entities[].physics2d.bodyTyperef:#/$defs/__schema0 | enum (4) | yes | none | {"enum":["dynamic","fixed","kinematicVelocity","kinematicPosition"]} | Rapier 2D rigid-body type. A body of any type nested below a dynamic or kinematic body is rejected: Rapier has no parent/child body relationship. Nesting below a fixed or physics-less transformed parent is supported for fixed bodies. Dynamic and kinematic bodies additionally require a conformal parent chain (uniform scale plus rotation/reflection), because later body rotation cannot round-trip through non-uniform parent scale without shearing the Pixi visual. |
# $.entities[].physics2d.colliderref:#/$defs/__schema0 | oneOf (3) | yes | none | none | Collider shape attached to the body. Its pose and dimensions use the composed parent transform at spawn. Cuboids support non-uniform scale; ball/capsule colliders reject non-uniform scale because Rapier cannot represent an ellipse. |
# $.entities[].physics2d.colliderref:#/$defs/__schema0 oneOf[0] | object | yes | none | {"additionalProperties":false} | Missing source description |
# $.entities[].physics2d.collider.shaperef:#/$defs/__schema0 oneOf[0] | const "cuboid" | yes | none | {"const":"cuboid"} | Box collider aligned to the rigid-body rotation |
# $.entities[].physics2d.collider.halfExtentsref:#/$defs/__schema0 oneOf[0] | array | yes | none | none | Half-width and half-height [hx, hy] in pixels |
# $.entities[].physics2d.collider.halfExtents[0]ref:#/$defs/__schema0 oneOf[0] | number | yes | none | none | Missing source description |
# $.entities[].physics2d.collider.halfExtents[1]ref:#/$defs/__schema0 oneOf[0] | number | yes | none | none | Missing source description |
# $.entities[].physics2d.colliderref:#/$defs/__schema0 oneOf[1] | object | yes | none | {"additionalProperties":false} | Missing source description |
# $.entities[].physics2d.collider.shaperef:#/$defs/__schema0 oneOf[1] | const "ball" | yes | none | {"const":"ball"} | Circle collider |
# $.entities[].physics2d.collider.radiusref:#/$defs/__schema0 oneOf[1] | number | yes | none | none | Radius in pixels |
# $.entities[].physics2d.colliderref:#/$defs/__schema0 oneOf[2] | object | yes | none | {"additionalProperties":false} | Missing source description |
# $.entities[].physics2d.collider.shaperef:#/$defs/__schema0 oneOf[2] | const "capsule" | yes | none | {"const":"capsule"} | Capsule collider (vertical) |
# $.entities[].physics2d.collider.halfHeightref:#/$defs/__schema0 oneOf[2] | number | yes | none | none | Half the straight segment length |
# $.entities[].physics2d.collider.radiusref:#/$defs/__schema0 oneOf[2] | number | yes | none | none | Cap radius |
# $.entities[].physics2d.sensorref:#/$defs/__schema0 | boolean | no | none | none | If true, a sensor (trigger) collider — overlaps fire onTriggerEnter/Exit, no solid response |
# $.entities[].physics2d.densityref:#/$defs/__schema0 | number | no | none | none | Collider density (drives mass). Default 1 |
# $.entities[].physics2d.frictionref:#/$defs/__schema0 | number | no | none | none | Coefficient of friction. Default 0.5 |
# $.entities[].physics2d.restitutionref:#/$defs/__schema0 | number | no | none | none | Bounciness 0..1. Default 0 |
# $.entities[].physics2d.linearDampingref:#/$defs/__schema0 | number | no | none | none | Linear velocity damping. Default 0 |
# $.entities[].physics2d.gravityScaleref:#/$defs/__schema0 | number | no | none | none | Per-body gravity multiplier. Default 1 |
# $.entities[].physics2d.lockRotationsref:#/$defs/__schema0 | boolean | no | none | none | Lock the body so it cannot rotate. Default false |
# $.entities[].componentsref:#/$defs/__schema0 | object | no | none | {"additionalProperties":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"anyOf":[{"anyOf":[{"type":"number"},{"type":"string"},{"type":"boolean"}]},{"type":"array","items":{"type":"number"}},{"type":"array","items":{"type":"string"}},{"type":"array","items":{"type":"boolean"}}]}},"propertyNames":{"type":"string"}} | User-defined components (validated against the world2d component registry) |
# $.entities[].components{key}ref:#/$defs/__schema0 | object | no | none | {"additionalProperties":{"anyOf":[{"anyOf":[{"type":"number"},{"type":"string"},{"type":"boolean"}]},{"type":"array","items":{"type":"number"}},{"type":"array","items":{"type":"string"}},{"type":"array","items":{"type":"boolean"}}]},"propertyNames":{"type":"string"}} | Missing source description |
# $.entities[].components{key}{key}ref:#/$defs/__schema0 | anyOf (4) | no | none | none | Missing source description |
# $.entities[].components{key}{key}ref:#/$defs/__schema0 anyOf[0] | anyOf (3) | no | none | none | Missing source description |
# $.entities[].components{key}{key}ref:#/$defs/__schema0 anyOf[0] anyOf[0] | number | no | none | none | Missing source description |
# $.entities[].components{key}{key}ref:#/$defs/__schema0 anyOf[0] anyOf[1] | string | no | none | none | Missing source description |
# $.entities[].components{key}{key}ref:#/$defs/__schema0 anyOf[0] anyOf[2] | boolean | no | none | none | Missing source description |
# $.entities[].components{key}{key}ref:#/$defs/__schema0 anyOf[1] | array | no | none | none | Missing source description |
# $.entities[].components{key}{key}[]ref:#/$defs/__schema0 anyOf[1] | number | yes | none | none | Missing source description |
# $.entities[].components{key}{key}ref:#/$defs/__schema0 anyOf[2] | array | no | none | none | Missing source description |
# $.entities[].components{key}{key}[]ref:#/$defs/__schema0 anyOf[2] | string | yes | none | none | Missing source description |
# $.entities[].components{key}{key}ref:#/$defs/__schema0 anyOf[3] | array | no | none | none | Missing source description |
# $.entities[].components{key}{key}[]ref:#/$defs/__schema0 anyOf[3] | boolean | yes | none | none | Missing source description |
# $.entities[].childrenref:#/$defs/__schema0 | array | no | none | none | Child entities |
# $.entities[].children[]ref:#/$defs/__schema0 | ref #/$defs/__schema0 | yes | none | none | Missing source description |