Theme:

World

world is a global singleton.

Objects


// Use these at runtime to add/remove objects

// Registers world-managed behavior on an object and its descendants.
// An unparented object is also attached to world.scene by default.
world.add(object: U.Object3D, addToScene: boolean = true)

// Remove an object and its descendants from runtime systems and the hierarchy
world.remove(object)


// list of objects that .update() each frame
world.objects -> Array of Objects

// list of objects which are raycasted each frame
world.raycastables -> Array of Objects

// make an object grabbable at runtime
world.addGrabbable(object)

// Register one mesh or text object for interaction raycasting
world.addRaycastable(mesh)

// Register a planar mesh for realtime planar reflections.
// Returns its stable reflection slot (0-7), or -1 if the geometry is not
// planar or all slots are occupied.
world.addPlanarReflection(mesh)

// Release a previously registered planar-reflection slot.
world.removePlanarReflection(mesh)

Up to eight planes may be registered. With one registered plane, its full-raster cadence is controlled by SINGLE_REFLECTION_RASTER_INTERVAL in Backend/PlanarReflection.js, and intervening eligible frames use reprojection. With two or more registered planes, one eligible plane receives a full raster capture per frame in round-robin order while the other eligible captures are reprojected. Planes outside the camera frustum, hidden planes, and planes whose front normal faces away from the camera are skipped. Both ordinary BufferGeometry data and the packed geometry used by BatchedMesh are supported. All vertex normals must point in roughly the same direction, and all triangle faces must be roughly coplanar. The shared local normal is transformed with the object, and the reflection plane passes through the transformed center of the geometry bounding box. Removing a registered mesh with world.remove() also releases its reflection slot.

Adding runtime objects

Use world.add(object) for a top-level runtime object. It discovers descendant update/preUpdate callbacks and point/spot lights, then attaches an unparented object to world.scene.

const model = await Model('prop.glb')
world.add(model)

For an ordinary visual child, parent.add(child) is enough: Unia synchronizes the child and queues its descendants for rendering.

parent.add(model)

If a late-added subtree defines update/preUpdate callbacks or contains point/spot lights, register that behavior after parenting it:

parent.add(child)
world.add(child)

Because child already has a parent, world.add() does not reparent it. addToScene = false only suppresses automatic scene attachment for an unparented object. Configure collider before adding a mesh. Raycasting is separate and world.addRaycastable() accepts individual meshes or text, not a Group.

Registered ordinary meshes and custom-shader meshes raycast their full CPU triangle geometry by default. Set mesh.raycastBoundsOnly = true to use only the mesh's world-space axis-aligned bounding box. The property is undefined by default, and only strict true enables the bounds-only path. This can be useful for vertex shaders that visually deform a mesh, provided the local geometry.boundingBox contains the full deformation.

Avatars

world.avatars -> Map of avatar UUIDs to Objects
world.avatar -> Your avatar

// Distance in metres at which streamed avatar models become eligible to load.
// The default is 70. Avatar models unload 10 metres beyond this distance.
world.avatarLoadDistance -> number

Set world.avatarLoadDistance to suit the scale and sightlines of the project. For example, a project that needs distant players to remain visible can set it in index.js:

world.avatarLoadDistance = 120

An avatar inside this distance loads when it is in view. The unload distance is always world.avatarLoadDistance + 10, which provides hysteresis near the load boundary.

Other


// Exclude object from all raycasting
world.setRaycastable(Object3D, boolean)
// or use object.raycastable = false before adding to the scene

world.username -> 'yourUserName' | null
world.scene -> U.Scene
world.renderer -> WebGPU renderer interface
world.physics -> Physics global, see physics docs
world.nav -> JavaScript navigation heightfield service, see Navigation docs
world.storage -> Storage global, see storage docs
world.camera - > U.PerspectiveCamera, the player camera
world.animationMixer -> U.AnimationMixer, the main animation mixer

world.XR -> Boolean, whether we are in XR or not
world.startXR()

world.stats ->
{
    triangles: number,
    calls: number,
    FPS: number,
}

Runtime mesh outlines

The renderer can outline one or more ordinary, non-skinned batched meshes. Pass all visible mesh children when highlighting a multipart model; groups and selection hitboxes are not expanded automatically.

world.renderer.setOutline(meshes, {
	color: [1, 1, 1, 1],
	width: 4, // screen pixels
	xRay: false, // false keeps the outline behind scene depth
})

world.renderer.clearOutline()

The selection mask stores coverage and the nearest selected depth in two channels. When xRay is false, the outline is hidden by nearer scene geometry that writes depth, including geometry in front of the selected object. xRay: true draws the outline through that geometry. Translucent surfaces that do not write depth cannot occlude it.

Only one runtime outline set is active at a time. Clear it when its owning gameplay system stops or removes the highlighted objects. Editor selection uses the same render pass but remains separate from the runtime target.

Scene triangle statistics

world.stats.triangles is the triangle count for the latest main scene frame, including custom shaders, skinned meshes, text, UI, background, and impostors. Each rendered instance contributes separately. Batched meshes use their selected LOD and existing draw ranges after visibility and occlusion selection.

world.stats.customShaderTriangles is the custom shader portion of that total, including indexed, non-indexed, and instanced geometry. Triangle lists use the submitted index/vertex count divided by three, rounded down; triangle strips use count minus two. Lines and points contribute zero triangles. Degenerate triangles still count, as they do in conventional draw-count statistics.

Both XR eyes and repeated depth/color/UI passes share one frame count. Objects rendered in either eye count once. Shadow maps, reflection captures, outline postprocessing, and compute work do not add to this scene geometry count. Counts use existing draw metadata: no index scans, GPU readbacks, or GPU allocations. These values measure submitted scene triangles, not unique vertices, GPU memory, vertex shader invocations, or shader complexity.