Clear method for TransformAccessArray

Hi,

I’m working with TransformAccessArray and I’m wondering why there isn’t any fast method to clear such array without the need to reallocating it.

I’m creating a TransformAccessArray with capacity 1000. Filling it with Add and would like to clear and resuse it for the next frame.

To my understanding and from the documentation of RemoveAtSwapBack() this should be possible by just setting the length to 0. But length is readonly.

I compared all available options for 10000 Transforms

  • Init: Allocate; Update: SetTransform(fixedSizeManagedArr) → 2.67ms

  • Init: _; Update: Allocate, Add, Dispose → 3.05ms

  • Init: Allocate; Update: Add, SetTransform(emptyArr) → 3.06

  • Init: Allocate; Update: SetTransform(list.ToArray()) → 3.35

  • Init: Allocate; Update: Add, for-reverse(){RemoveAtSwapBack) → 3.37

As I don’t have a fixed sized managed array, allocating and disposing everyframe is still the fastest option and I would hope that just clearing would be significant faster.

1 Like

Given that at the moment there is no way to clear a TransformAccessArray, it makes me question, which is the best way to emulate that?:

A) Dispose old TransformAccessArray, create new and populate with .Add(int) or .Add(Transform). (May be Burst compatible)

B) Reuse the old TransformAccessArray and use the Transform this[int] indexer to set new transforms, then do a loop with RemoveAtSwapBack to remove old transforms (if the new length is below the old length). (Only a part is Burst compatible).

C) Store all Transforms into a Transform[ ], then reuse the old TransformAccessArray and use the .SetTransforms(Transform[ ]) method.

D) Reuse the old TransformAccessArray do a loop with RemoveAtSwapBack to remove all old transforms, then do .Add(int) to populate the new ones. (Burst compatible).

Which version people use?

I think the intended workflow is to acquire a TransformAccessArray and keep it alongside lists/arrays of the transforms your tracking (and other data you need). You maintain (or obtain) lists of transforms that you are adding/removing from your system in the current frame. Then, you can use Add/RemoveAtSwapBack on each array to only add/remove the transforms that have changed since last frame. This isn’t as clean as rebuilding the arrays from scratch every frame, but works fast even without Burst, especially for low frequency changes. It’s reasonably easy to write code that avoids the lists ever going out of sync. (All arrays should always have the same length and indices correspond to data for the same object in each of the arrays.)

I didn’t realize there’s an Add(int instanceId) overload now, that’s handy for bursting more paths.

For reference see CompanionGameObjectUpdateTransformSystem. (This code stores index of each transform in an additional hash map, but for small transform counts you can get away with calling IndexOf for each object you’re removing from the lists. You can search for the index from the end of the array if you’re most likely to be removing the most recently-added transforms)

I see, but it’s an inconvenient way to work. It would be much easier if they added a Clear() method, like, how difficult that can be?

Just note that Add(int) overload is broken for some cases as depicted in Bug - TransformAccessArray.Add(int) behave different than TransformAccessArray.Add(Transform) - Unity Forum