Skip to content

Mesh Instancing

Instancing renders many copies of one object in a single draw – thousands of them stay cheap, because the GPU draws the shared mesh once and stamps it at each transform. Use it for fields, crowds, particles, and any procedural scatter.

Scatter copies

Give one object the set of transforms to render it at with setInstances(Instances.transforms([...])). Each transform is a Vector3 position (or a full transform):

javascript
var base = await scene.createEntity(
    createBox(0.03, 0.03, 0.03).anchor(Anchor.position(0, 0, -1.5))
);

var spots = [];
var count = 1000;
var goldenAngle = Math.PI * (3 - Math.sqrt(5));
for (var i = 0; i < count; i++) {
    var r = 0.4 * Math.sqrt(i / count);
    var a = i * goldenAngle;
    spots.push(new Vector3(r * Math.cos(a), 0, r * Math.sin(a)));
}
base.setInstances(Instances.transforms(spots));

Call setInstances again with a new set to re-scatter – for example, from an On Render handler or a slider's valueChanged.

Instancing vs cloning

Instances are rendering-only: they share the base object's mesh and material and are not individual entities. You can't tap one, script one, or give one its own physics body. When you need copies that behave independently – each collidable, tappable, or separately animated – use entity.clone() instead. Rule of thumb: dozens of interactive copies → clone; hundreds or thousands of visual copies → instance.

Shadows on dense fields

A large instanced field can alias the shared shadow map into streaks. Turn the projected shadow off for the base object so the field stays clean:

javascript
createBox(0.03, 0.03, 0.03).shadow({ directional: false });

Instancing needs iOS 26 or later. Gate a portable script with environment.features.has('instancing') – see Feature Detection.