Drawing by instances

Since SDK 0.2.1

An InstancedMesh draws copies of one mesh with one material, every frame, without a single GameObject: grass, crowds, debris, stars. You give a matrix per copy (where it is, how it turns, its size), and optionally a color, a float or a vector per copy. The game draws them with Graphics.RenderMeshInstanced, in packets of 1023, reading the matrices straight from the memory of the world.

The copies have no collision: to touch something, use ordinary objects. Instanced drawing exists on the players' devices only.

Draw

csharp
public class Meadow : FluxScript
{
    public Mesh blade;
    public Material material;
    private InstancedMesh _grass;

    protected override void Start()
    {
        _grass = InstancedMesh.Create(blade, material, 10000);
        var colors = _grass.AddColorProperty("_BaseColor");
        for (var i = 0; i < 10000; i++)
        {
            _grass.matrices[i] = Matrix4x4.TRS(new Vector3(i % 100 * 0.3f, 0, i / 100 * 0.3f), Quaternion.identity, Vector3.one);
            colors[i] = Color.Lerp(new Color(0.2f, 0.5f, 0.1f, 1f), new Color(0.5f, 0.8f, 0.2f, 1f), Random.value);
        }
        _grass.shadowCastingMode = ShadowCastingMode.Off;
    }

    protected override void OnDestroy() => _grass.Dispose();
}
  • InstancedMesh.Create(mesh, material, capacity, submesh): matrices holds capacity matrices, all at the origin until you place them.
  • count draws the first copies only (at most capacity); visible hides them all.
  • Change matrices and the per-copy arrays whenever you like, from any thread: each frame draws what they hold.
  • shadowCastingMode, receiveShadows, layer, mesh (or SetMesh(mesh, submesh)) and material can change at any time.
  • Dispose() (or Object.Destroy) stops the drawing. It stops with its world.

The material

The game turns GPU instancing on for the material. A per-copy property (AddColorProperty("_BaseColor"), AddFloatProperty, AddVectorProperty) is read only by a shader that declares it as an instanced property (UNITY_INSTANCING_BUFFER); with another shader, every copy has the material's own value.