Appearance
Content tiers: static, edits, live
You'll learn: the three ways content exists, what each costs, and how props come to rest and start moving. You'll need this when: your plot has lots of stuff in it.
Status: the tiers and per-lobby edits are Built (headless). Publishing static content (chunking, LODs, collision baking at publish) and the engine's physics for resting and moving props are Planned; today scene.wakeProp(id) calls your onPropStartMoving hook, and nothing comes to rest on its own.
Three tiers
| Tier | What | Cost per tick |
|---|---|---|
| 1. Published static | blocks, mesh terrain, static props (a placed glTF coffee table) | nothing. Chunked, LOD'd and collision-baked once, at publish; streamed as content-hashed chunks |
| 2. Per-lobby edits | changed blocks, moved or removed props, replaced mesh-terrain chunks | sent on change and on join, as a sparse diff |
| 3. Live entities | anything that moves or animates | replicated every tick, at each viewer's rate |
Rule of thumb: make things static unless they move. A cathedral of 10,000 props costs nothing per tick. Ten thousand entities is ten thousand things to replicate.
Props rest and move
A static prop can come alive when disturbed, then settle back:
ts
const rock = scene.create({
Transform: { pos: [12, 64, 30] },
Model: { asset: "models/boulder.glb" },
Collider: { shape: "mesh", body: "dynamic", restAfterSeconds: 1.0 }, // a prop until something hits it
});
export function onPropStartMoving(id: EntityId) {
if (id === rock) audio.play("sfx/rumble.ogg", { at: id });
}- Start moving: hit, pushed, or
scene.wakeProp(id). It becomes a live entity (onPropStartMoving). - Come to rest: when it stays still for
restAfterSeconds, its new pose is written to the lobby's edit layer and it's a static prop again (onPropStopMoving). Viewers swap it with no pop.