Scene (scene.yaml)
A scene file lists what's in a level: the camera, lights, placed actors and scripted objects, plus scene-wide lighting and the BT functions that run when the scene loads, updates and stops. Studio's Scene View, Hierarchy and Inspector edit it.
Your main scene is the file registered as scene under
files in the asset registry.
paths.scene in game.json can point to a different one.
Example
script:
lifecycle:
load: sceneLoad
update: sceneUpdate
stop: sceneStop
lighting:
ambient: [0.12, 0.12, 0.14]
shadows:
preset: quality
distance: 80
entities:
- id: main_camera
kind: camera
position: [0, 2, 8]
camera:
direction: [0, -0.2, -1]
field_of_view: 60
near_clip: 0.1
far_clip: 200
- id: sun
kind: directional_light
rotation: [-0.9, 0.4, 0]
light:
color: [1.0, 0.95, 0.9]
intensity: 3
source_radius: 0.5
- id: player_spawn
name: Player
kind: actor
actor: PlayerShip
position: [100, 0, 0]
script:
source: bt/player.bt
lifecycle:
load: playerLoad
update: playerUpdate
Top-level fields
| Field | Type | Default | Description |
|---|---|---|---|
format | map | none | Optional file format version; see File format versions. |
script.lifecycle | map | none | Scene-wide lifecycle hooks. |
lighting | map | engine defaults | Scene-wide lighting. |
entities | list | empty | Things in the scene; see Entities. |
You can add your own fields anywhere. The engine ignores them and Studio keeps them when it edits the file.
Vectors
Scenes and actor files write positions, rotations and colors as comma-separated numbers on one line, with or without brackets:
position: [1, 2, 3]
position: 1, 2, 3
Studio writes the bracketed form. Positions take 2 or 3 numbers ([x, y]
means z = 0). Rotations, directions and colors take exactly 3.
Entities
Each entity's kind says what it is. Entities with a kind the engine doesn't
know are ignored by the game (unless they have a script), so you can use your
own kinds for things your code reads.
| Field | Type | Default | Description |
|---|---|---|---|
id | string | — | Stable identifier. Required for lights and scripted entities. Up to 127 characters. |
name | string | id (lights) | Display name. |
kind | string | — | camera, actor, directional_light, point_light, spot_light, or your own. |
position | vector | [0, 0, 0] | World position. |
rotation | vector | [0, 0, 0] | Rotation in radians (x, y, z). Used by lights. |
script | map | none | Per-entity script hooks. |
Studio also reads model, material, size, health and collision on
entities to draw its preview. Not implemented in the game: the engine
doesn't create visuals or colliders for scene entities; your code does.
kind: camera
The first camera becomes the game's starting 3D camera. Other cameras are ignored. Without a camera, the game starts with a 2D camera the size of the window.
| Field | Type | Default | Description |
|---|---|---|---|
position | vector | [0, 0, 1] | Camera position. |
camera.direction | vector | [0, 0, -1] | Direction the camera looks. Can't be zero. |
camera.field_of_view | number | 72 | Vertical field of view in degrees, between 1 and 179. |
camera.near_clip | number | 0.04 | Nearest visible distance. Greater than 0. |
camera.far_clip | number | 180 | Farthest visible distance. Greater than near_clip. |
kind: actor
Places an actor from the asset registry. A scene can have up to 256 actor entities.
| Field | Type | Default | Description |
|---|---|---|---|
actor | string | — | Required. Actor name from the registry. |
position | vector | actor's spawn.position, else origin | Where to place it. |
The scene doesn't spawn actors by itself. Your BT code reads the placements
with worldSceneActors(), which gives each actor's name and position, and
creates them.
Lights
directional_light (sunlight), point_light and spot_light entities
create lights when the game loads.
| Field | Type | Default | Description |
|---|---|---|---|
id | string | — | Required. Unique among lights. |
position | vector | [0, 0, 0] | Light position (point and spot lights). |
rotation | vector | [0, 0, 0] | Radians. Sets which way directional and spot lights point; with no rotation they point along −Z. |
light.color | vector [r, g, b] | [1, 1, 1] | Light color (linear, not sRGB). |
light.intensity | number | 1 | Brightness. |
light.range | number | 15 | How far point and spot lights reach, in world units. |
light.inner_angle | number | ≈25.8 | Spot light: angle (degrees from center) where the light starts to fade. |
light.outer_angle | number | ≈37.2 | Spot light: angle where the light ends. Less than 90. |
light.source_radius | number | ≈0.27° (sun), 0.15 (others) | Size of the light, which makes shadow edges softer. Degrees for directional lights, world units for others. |
light.depth_bias | number | 0.005 | Raise if surfaces show shadow speckles ("shadow acne"); too high detaches shadows. |
light.normal_bias | number | 0.015 | Same purpose as depth_bias, along the surface direction. |
light.enabled | bool | true | Turn the light on or off. |
light.shadows | bool | true | The light casts shadows. |
light.resolution | integer | 0 | Shadow detail for this light. 0 uses the scene default; otherwise a power of two from 16 to 32768. |
light.priority | integer | 0 | When there isn't room for every shadow, higher-priority lights keep theirs. |
Lighting
If a scene has a lighting section, its values (and the defaults for keys it
leaves out) replace the engine's lighting settings.
| Field | Type | Default | Description |
|---|---|---|---|
lighting.enabled | bool | true | Scene lighting on or off. |
lighting.ambient | vector [r, g, b] | [0.18, 0.18, 0.18] | Light that reaches everything, even in shadow. |
lighting.shadows.preset | performance, balanced, quality or ultra | balanced | Starting shadow quality. The keys below override it. |
lighting.shadows.enabled | bool | true | Draw shadows. |
lighting.shadows.unlimited | bool | false | Update every shadow every frame with no limits. Best quality, slowest. |
lighting.shadows.distance | number | 100 | How far from the camera sunlight shadows are drawn. |
lighting.shadows.atlas_size | integer | preset | Width of the shadow texture shared by all lights. Power of two, 16–32768. |
lighting.shadows.atlas_height | integer | preset | Height of that texture. 0 means square; otherwise a multiple of 16, at most 32768. |
lighting.shadows.directional_resolution | integer | preset | Default shadow detail for sunlight. Power of two, 16–32768. |
lighting.shadows.local_resolution | integer | preset | Default shadow detail for point and spot lights. Power of two, 16–32768. |
lighting.shadows.max_resident_lights | integer | unlimited | Most lights that can have shadows at once. -1 is unlimited. |
lighting.shadows.refresh_views | integer | preset | Shadow views updated per frame (a sun uses 4, a point light 6, a spot light 1). Lower is faster; -1 is unlimited. |
lighting.shadows.filter | low, medium or high | preset | Shadow edge smoothness. |
| Preset | atlas_size | atlas_height | directional_resolution | local_resolution | refresh_views | filter |
|---|---|---|---|---|---|---|
performance | 4096 | 0 | 1024 | 256 | 24 | low |
balanced | 4096 | 0 | 1024 | 256 | 24 | medium |
quality | 8192 | 0 | 2048 | 512 | 64 | high |
ultra | 16384 | 11264 | 4096 | 1024 | 128 | high |
Lifecycle hooks
Hooks name BT functions that run at points in the scene's life. The functions
must be in your compiled scripts (bt.sources or something they include);
if one is missing, the game stops with an error at startup.
| Key | Scene-wide function | Runs |
|---|---|---|
load | fn name() -> void | Once, when the scene loads, before bt.entry and the UI start. |
start | fn name() -> void | Once, after everything created in load has started. |
update | fn name(float dt) -> void | Every simulation step. |
draw | fn name(float dt) -> void | Every frame, while the world is drawn. |
overlay | fn name(float dt) -> void | Every frame, after the world, for drawing on top of it. |
stop | fn name() -> void | Once, when the game shuts down. |
Entity scripts
Give an entity a script.lifecycle to run hooks for it. Scripted entities
need an id; a scene can have up to 256.
| Field | Type | Description |
|---|---|---|
script.source | string | The script file Studio opens for this entity. It is not compiled automatically: list it in bt.sources or include it. |
script.lifecycle.<phase> | string | Function for load, start, update, draw, overlay or stop. |
Entity hooks receive the entity's details:
| Phase | Function |
|---|---|
load, start, stop | fn name(string id, string kind, float x, float y, float z) -> void |
update, draw, overlay | fn name(string id, string kind, float x, float y, float z, float dt) -> void |
x, y, z are the position written in the scene.
Order: the scene-wide hook runs first, then entity hooks in file order. On
shutdown, entity stop hooks run in reverse order, then the scene-wide
stop. If load fails, the game doesn't start. If a per-frame hook fails,
that hook stops running, but stop still runs.
Limits
- 256 actor entities and 256 scripted entities per scene.
- IDs, kinds, actor names and hook names: up to 127 characters. Light names: up to 63.
- Nested key paths (such as
entities.3.light.color) up to 127 characters. - Other YAML rules: see Asset registry: YAML rules.
Errors
| Message | Cause |
|---|---|
scene file: `version: 1` is no longer used | Delete the version line (an older file). |
scene file uses format version X; this cTurtle reads format … | The file was written for a newer cTurtle; see File format versions. |
could not parse scene YAML | Unsupported YAML, or a key path that's too long. |
scene script.lifecycle.X must name a BtLang function | Hook value isn't a function name. |
scripted scene entity N requires an id | Scripted entity without id. |
actor entity N requires an actor reference | kind: actor without actor. |
... entity N has invalid position / invalid direction | Wrong number of components, or not numbers. |
camera entity N has zero direction | camera.direction is [0, 0, 0]. |
camera entity N field_of_view must be between 1 and 179 degrees | FOV out of range. |
camera entity N requires 0 < near_clip < far_clip | Invalid clip distances. |
scene has more than 256 actor records / scripted entities | Too many. |
scene references an unknown actor: X | Register the actor in the asset registry. |
scene lifecycle function is missing: X, scene entity lifecycle function is missing: X | The function isn't in your compiled scripts. |
entities.N.id: light requires a stable ID shorter than 128 bytes | Light without id. |
entities.N.kind: duplicate light ID | Two lights share an id. |
entities.N.light: invalid light color, intensity, range, cone, source size, bias, or resolution | A light value is out of range. |
lighting.shadows.preset: unknown preset, lighting.shadows: invalid resolution, atlas dimensions, or distance | Fix the lighting value. |
See also
- Actors
- Asset registry
- game.json:
paths.scene,bt.sources,bt.entry