InstancedModel
InstancedModel draws a registered model once for each placement in a list, in one draw call for each mesh in the model. Use it for a forest, a field of coins or a scree of rocks: things that stand many times and do nothing on their own. It spawns no entity, so a copy has no behaviours, no collider and no transform a system moves. A thing that moves, collides or is picked up is an <Entity model>.
A placement is a plain transform, so any code can produce the list:
position: the point the model’s lowest point stands on. The model is seated on its own bounds, as the scatter kit is, so a model centred on its origin still stands on the ground.turn: radians about y. It defaults to 0.scale: a multiple of the model’s own size, one number for every axis or one for each. It defaults to 1.tint: a colour the copy is multiplied by. Copies without one keep the model’s own colours.
Its props are in InstancedModelProps and a placement’s fields in InstancePlacement.
Unity’s Graphics.RenderMeshInstanced, Unreal’s Instanced Static Mesh and Godot’s MultiMeshInstance3D take the same input: one mesh and a list of transforms.
The copies are never culled one by one and have no level of detail: the whole batch draws whenever any of it is in view. A headless scene draws nothing and loads no model.
Where it runs
Section titled “Where it runs”Client. The copies only change how the world looks.
import { InstancedModel, registerModel } from "@daniel-zarinski/engine";import fir from "./fir.glb?url";
registerModel("fir", fir);
const firs = Array.from({ length: 50 }, (_, index) => ({ position: [index * 3, 0, -10] as [number, number, number], turn: index, scale: 1 + (index % 3) * 0.2,}));
export function Treeline() { return <InstancedModel model="fir" placements={firs} />;}