Adding Props¶
Status: Current Last reviewed: 2026-07-07
A prop is a prefab: a gameplay definition in shared/src/prefabs.ts and a visual in client/src/render/prefabs.ts. Once both exist it appears in the /admin palette automatically.
The Two Halves¶
Gameplay definition (shared/src/prefabs.ts). Add a PrefabDef:
Fields: id, name, category, collider (null, circle, or aabb at scale 1), blockHeight (projectile block height; 0 lets shots pass over). Options: instanced (batch into one mesh), marker (gameplay-only, invisible in play), defaults (starting props for new instances).
Visual (client/src/render/prefabs.ts). Either:
- Add a case to
buildPrefabVisualthat returns aTHREE.Group, for a one-off prop, or - Add an entry to
INSTANCED_PREFABS(a list ofInstancePartgeometry/material/offset), for a prop that will appear many times.
The server derives colliders from the shared def; the client renders from the visual. They agree because both read the same ZoneObjectInstance.
Instanced versus Unique¶
Use instanced parts for anything placed in bulk (trees, rocks, crates, barrels, fences, mushrooms, hay, bone piles). The client batches all instances of that prefab into a single InstancedMesh, which is one draw call. Use buildPrefabVisual for structures and one-offs (houses, the smithy, the ember relay, the cave gate).
Placing¶
Restart the client so the new prefab is bundled, open /admin, find it in its palette category, click to place, adjust in the inspector, and Save Zone.
Markers¶
Marker prefabs (player_spawn, mob_spawn, quest_trigger, safe_zone, audio_emitter) return null from buildPrefabVisual, so they are invisible in the game client. The editor draws its own coloured gizmo for them. Use markers for anything that is data rather than scenery.
Performance
Prefer instanced props for repeated scenery and keep unique-mesh props for things that genuinely need custom geometry. Draw calls, triangles, and active entities are all visible in the in-game performance overlay (F3), so you can check the cost of a new prop directly.