NodeWorld

Lots d'objets

Depuis SDK 0.2.1

Changer un transform depuis un script traverse la frontière entre ton module et le jeu une fois par valeur. Pour quelques objets, ça ne compte pas ; pour des centaines ou des milliers, utilise un ObjectBatch : il garde un tableau par valeur (positions, rotations, échelles, état actif, propriétés de matériau), une case par objet, dans la mémoire du monde. Le jeu remplit les tableaux que tu lis avant Update et applique les tableaux que tu écris après LateUpdate, tout d'un coup : les transforms par un job Burst qui lit directement la mémoire du monde.

Les lots n'existent que sur les appareils des joueurs (le serveur n'a pas de rendu).

Faire un lot

csharp
// Les enfants d'un objet (pas leurs propres enfants), dans leur ordre :
var batch = ObjectBatch.FromChildren(transform, BatchFields.Position, BatchFields.Position | BatchFields.Rotation, BatchSpace.Local);

// Une liste d'objets du monde :
var batch2 = ObjectBatch.Create(new[] { a, b, c }, BatchFields.None, BatchFields.Active);

// Les objets actifs du monde qui ont une étiquette (tag) :
var batch3 = ObjectBatch.WithTag("Bee", BatchFields.Position, BatchFields.None);
  • Le deuxième argument dit quels tableaux le jeu remplit avant chaque Update (ceux que tu lis), le troisième quels tableaux il applique après chaque LateUpdate (ceux que tu écris). Un champ peut être dans les deux.
  • BatchSpace.World travaille avec position, rotation et l'échelle dans le monde ; BatchSpace.Local avec localPosition, localRotation et localScale.
  • Les objets sont ceux de la liste, des enfants ou de l'étiquette au moment où le lot est fait.
  • Les tableaux que tu lis sont remplis tout de suite quand le lot est fait, puis avant chaque Update.

Utiliser les tableaux

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) et active (bool) sont les tableaux ; un tableau que le lot n'a pas vaut null. GetObject(i) donne l'objet de la case i.
  • AddColorProperty, AddFloatProperty et AddVectorProperty donnent un tableau d'une propriété de matériau par objet, appliqué après LateUpdate au renderer de chaque objet seul (comme Renderer.SetColor : le matériau partagé ne change pas). Leur deuxième argument est l'index du matériau du renderer (0 par défaut).
  • Un thread de ton script (Parallel.For) peut remplir les tableaux ; le jeu les applique après LateUpdate.
  • Dispose() (ou Object.Destroy(batch)) arrête le lot. Un lot s'arrête avec son monde.