I think I’ve got the best outcome…
Same amount of colliders per compound collider. Completely avoided mem alloc, saving roughly 8ms per job.
I started by creating a lot of colliders in OnCreate. I create the max amount of colliders one of my compound colliders could possibly use, multiplied by thread count. This is my colliderPool.
private void SetupColliderPool()
{
int threadCount = JobsUtility.JobWorkerCount + 1;
int total = threadCount * PooledCollidersPerThread;
colliderPool = new NativeArray<BlobAssetReference<Collider>>(total, Allocator.Persistent);
NativeArray<BlobAssetReference<Collider>> pool = colliderPool;
// this takes roughly 100ms regardless of thread count.
Parallel.For(0, threadCount, t =>
{
int start = t * PooledCollidersPerThread;
for (int i = start; i < start + PooledCollidersPerThread; i++)
{
pool[i] = BoxCollider.Create(new BoxGeometry() { Orientation = quaternion.identity, Size = 0f });
}
});
}
Next, in the job where I will be creating a compound collider, I create a slice of the colliderPool for the thread so it does not compete with any other threads for the pooled colliders it will work with. I use the unsafe context to change the geometry of pooled colliders, and use them to construct a compound collider. I could modify this so that if no pooled colliders are left, I expand the pool, or create new colliders, but for now I don’t need to do so.
createBoxColliderProfilingMarker.Begin();
var poolSlice = new NativeSlice<BlobAssetReference<Collider>>(pool, (nativeThreadIndex - 1) * PooledCollidersPerThread, PooledCollidersPerThread);
for (int i = 0; i < count; i++)
{
BlobAssetReference<Collider> collider = poolSlice[i];
unsafe
{
BoxCollider* bcPtr = (BoxCollider*)collider.GetUnsafePtr();
BoxGeometry boxGeom = bcPtr->Geometry;
boxGeom.Size = colliderGenData[i].Size;
bcPtr->Geometry = boxGeom;
}
compoundChildren[i] = new CompoundCollider.ColliderBlobInstance()
{
CompoundFromChild = new RigidTransform(quaternion.identity, colliderGenData[i].Center),
Collider = collider
};
}
createBoxColliderProfilingMarker.End();
So in summary, every time I create the compound collider I am reusing the same pooled box colliders. This results in no memory allocations for box colliders (apart from once in OnCreate). I still have a mem alloc for the compound collider but that seems to be no issue.
It seems to be working just fine. Is there any reason why this might come back to bite me… or a reason why this is not recommended? If not, do you think we could get access to change the geometry without needing the unsafe context?
Thanks for your help 