Log inGet started

Getting started

This is the one read that shows how the pieces fit together. Each system has its own guide; this walks the whole chain once — world → scene → players + camera → entities → components + assets —…

You're always in a world

When the engine is running, you're in a world — a live, shared, persistent project (the worlds guide). You don't open or create one to start; you're already in it. Everything you author lands in the world's source and is shared with everyone connected, with no save step (the engine guide covers persistence).

A world boots from two files in its source:

  • .world_settings — configuration: the startup scene, renderer/physics/lsp/ui settings, and the default avatar a "user_profile" player slot binds.
  • .world_entrypoint.luau — a script with onWorldLoad() / onWorldUnload() that runs when the world binds. It seeds the defaults, sets the theme, and loads the startup scene.

You rarely write these from scratch — every world ships them — but knowing they exist explains "what runs first."

The startup scene loads

.world_settings names a startup_scene; the entrypoint loads it with layers.load. A scene assembles a playable space (the scenes guide); loading one as the root replaces the previous root and brings its entities in.

layers.load("scenes.main")          -- what the entrypoint does for you
layers.active                        -- the loaded root scene

A scene declares how it handles players and camera

A scene says who plays it with a single player intent in its scene.json: "spawns" (the scene spawns a player for each joining user) or "none" (no player; author a Camera entity for the view). Players and cameras are authored entities you can see in the scenegraph.

A "spawns" scene carries a small authored structure: a PlayerPrototype (a template player-setup subtree) whose body names a body entity under it (the avatar — e.g. an Asset pointing at @builtin::avatars.humanoid), a CameraRig Camera under it (each user's own view), and a PlayerSpawn that names the prototype and marks where players appear. On join, the engine clones the prototype for that user, adopts the clone's body as their avatar, and points the CameraRig at it. A fresh scene (asset.create("scene", …)) starts with this structure already in place, so it boots into a playable player + camera.

You access the live player through the scene's registry — you don't create it:

local me = layers.active.players.localPlayer   -- the player this client controls
layers.active.camera                            -- the play-mode camera proxy

Re-resolve layers.active.players.localPlayer when you need it rather than stashing it — it's re-established across mode flips. The built-in avatar bundles (@builtin::avatars.humanoid, editor_pill, …) and camera controllers (@builtin::controller.third_person, free, first_person, orbit, …) are the menu; the prototype's PlayerPrototype.body entity is the body every player spawns with. (Player intent, PlayerPrototype / PlayerSpawn, and the camera in depth: the scenes guide.)

You populate the scene with entities and assets

An entity is a named handle with a transform and a place in a hierarchy (the entities guide). On its own it does nothing — its form comes from an asset you reference. The normal way to place real, recognizable content is to survey the library and bring in an asset that packages it (a bundle is mesh + material + rig together):

asset.list("bundle")                                          -- survey what exists, e.g. @builtin::avatars.humanoid
tools.use("entityOps", "fromAsset", "@builtin::avatars.humanoid", { name = "guard" }) -- reference one and spawn it

That's the rhythm for everything: survey what exists (the ZeroMind library first), reuse or adapt it, generate it from a description when nothing fits, and hand-author only when generation doesn't (the asset-system and generating-assets-and-content guides). What gives an entity its form is always a real asset — found in the library, generated, or authored.

Capabilities come from components

An entity gains behaviour by adding components:

entity.find("guard").component.add("Light", { intensity = 5 })   -- a component gives it behaviour

Components are authored types with a lifecycle (the components guide). Whenever nothing in @builtin or the shared ZeroMind library fits — a model, a material, a behaviour, a whole new kind of thing — you author it; that's the normal path, not a fallback.

That's the chain

world (you're in one, shared) → its startup_scene loads → the scene's player intent brings in your player + camera (from the PlayerSpawn it authors), which you access → you spawn entities → you give them components (behaviour) and assets (content). Everything else — physics, ui, audio, multiplayer, performance — hangs off those. Read the system guide for whatever you're touching, survey before you build, and verify against the running engine (the discovering guide).

  • documentation
  • guide