Object batches
Since SDK 0.2.1
Changing a transform from a script crosses the boundary between your module and the game once per value. For a few objects it does not matter; for hundreds or thousands, use an ObjectBatch: it holds one array per value (positions, rotations, scales, active state, material properties), one entry per object, in the memory of the world. The game fills the arrays you read before Update and applies the arrays you write after LateUpdate, all at once: the transforms by a Burst job that reads the memory of the world directly.
Batches exist on the players' devices only (the server has no rendering).
Make a batch
csharp
// The children of an object (not their own children), in their order:
var batch = ObjectBatch.FromChildren(transform, BatchFields.Position, BatchFields.Position | BatchFields.Rotation, BatchSpace.Local);
// A list of objects of the world:
var batch2 = ObjectBatch.Create(new[] { a, b, c }, BatchFields.None, BatchFields.Active);
// The active objects of the world with a tag:
var batch3 = ObjectBatch.WithTag("Bee", BatchFields.Position, BatchFields.None);- The second argument says which arrays the game fills before each
Update(the arrays you read), the third which arrays it applies after eachLateUpdate(the arrays you write). A field may be in both. BatchSpace.Worldworks withposition,rotationand the scale in the world;BatchSpace.LocalwithlocalPosition,localRotationandlocalScale.- The objects are those of the list, the children or the tag when the batch is made.
- The arrays you read are filled at once when the batch is made, then before every
Update.
Use the arrays
csharp
public class Dancers : FluxScript
{
private ObjectBatch _batch;
private Color[] _colors;
protected override void Start()
{
_batch = ObjectBatch.FromChildren(transform, BatchFields.Position, BatchFields.Position | BatchFields.Rotation, BatchSpace.Local);
_colors = _batch.AddColorProperty("_BaseColor");
}
protected override void Update()
{
for (var i = 0; i < _batch.count; i++)
{
_batch.positions[i].y = 0.3f * Mathf.Sin(Time.time * 3f + i * 0.2f);
_batch.rotations[i] = Quaternion.Euler(0, Time.time * 90f, 0);
_colors[i] = Color.Lerp(Color.red, Color.blue, i / (float)_batch.count);
}
}
protected override void OnDestroy() => _batch.Dispose();
}positions,rotations,scales(Vector3, Quaternion, Vector3) andactive(bool) are the arrays; an array the batch does not have isnull.GetObject(i)gives the object at indexi.AddColorProperty,AddFloatPropertyandAddVectorPropertygive an array of a material property per object, applied afterLateUpdateto each object's renderer alone (asRenderer.SetColor: the shared material does not change). Their second argument is the material index of the renderer (0 by default).- A thread of your script (
Parallel.For) may fill the arrays; the game applies them afterLateUpdate. Dispose()(orObject.Destroy(batch)) stops the batch. A batch stops with its world.
