private void DoTest()
        {
            var amount = PerformanceComparisonConfig.ObjectCount;
            var world  = new BVHTreeWorld(amount, Allocator.Persistent);

            Random.InitState(0);
            var colliders  = new NativeArray <Collider>(amount, Allocator.TempJob);
            var transforms = new NativeArray <RigidTransform>(amount, Allocator.TempJob);

            for (int i = 0; i < PerformanceComparisonConfig.ObjectCount; i++)
            {
                colliders[i]  = BoxCollider.Create(float3.zero, PerformanceComparisonConfig.GetRandomSize());
                transforms[i] = new RigidTransform(quaternion.identity, PerformanceComparisonConfig.GetRandomPosition());
            }


            var s = Stopwatch.StartNew();

            Profiler.BeginSample("broad");
            new BVHTreeWorld.InsertCollidersAndTransformsJob {
                Tree       = world.tree,
                Bodies     = world.bodies,
                Colliders  = colliders,
                Transforms = transforms
            }.Run();
            Profiler.EndSample();
            if (enableLog)
            {
                Debug.Log("Building broad phase took: " + s.Elapsed.TotalMilliseconds);
            }

            var rayResult = new NativeList <int>(64, Allocator.TempJob);

            var start = PerformanceComparisonConfig.RayStart;
            var end   = PerformanceComparisonConfig.RayEnd;

            var rayJob = new RayJob {
                Tree     = world.tree,
                RayInput = new NativeBVHTree.Ray {
                    origin      = start,
                    direction   = math.normalize(end - start),
                    maxDistance = math.distance(start, end),
                },
                Results = rayResult
            };

            s.Restart();
            rayJob.Run();
            if (enableLog)
            {
                Debug.Log("Raycasts took: " + s.Elapsed.TotalMilliseconds + " results: " + rayResult.Length);
            }

            s.Restart();
            world.Update();
            if (enableLog)
            {
                Debug.Log("Building broad phase again after no changes took: " + s.Elapsed.TotalMilliseconds);
            }

            for (int i = 0; i < 100; i++)
            {
                int randomIndex = Random.Range(1, PerformanceComparisonConfig.ObjectCount);
                world.UpdateTransform(randomIndex, new RigidTransform(quaternion.identity, PerformanceComparisonConfig.GetRandomPosition()));
            }
            s.Restart();
            world.Update();
            if (enableLog)
            {
                Debug.Log("Building broad phase again after some changes took: " + s.Elapsed.TotalMilliseconds);
            }
        }
        public IEnumerator Test()
        {
            int amount = 3000;

            Random.InitState(0);
            var go = new GameObject("debug");

            go.AddComponent <NativeBVHDebugDrawer>();
            var world = new BVHTreeWorld(amount, Allocator.Persistent);

            var movingObjects = new List <MovingObject>();

            NativeBVHDebugDrawer.LastTree = world.tree;
            NativeList <Collider> colliders = new NativeList <Collider>(amount, Allocator.TempJob);

            for (int i = 0; i < amount / 2; i++)
            {
                var center = new float3(UnityEngine.Random.Range(0, 0), UnityEngine.Random.Range(0, 0), UnityEngine.Random.Range(0, 0));
                var size   = new float3(UnityEngine.Random.Range(1, 3), UnityEngine.Random.Range(1, 3), UnityEngine.Random.Range(1, 3));
                colliders.Add(BoxCollider.Create(center, size));
            }

            for (int i = 0; i < amount / 2; i++)
            {
                var center = new float3(UnityEngine.Random.Range(0, 0), UnityEngine.Random.Range(0, 0), UnityEngine.Random.Range(0, 0));
                colliders.Add(SphereCollider.Create(center, UnityEngine.Random.Range(10, 15)));
            }

            new BVHTreeWorld.InsertJob {
                Tree      = world.tree,
                Bodies    = new NativeList <BVHTreeWorld.Body>(0, Allocator.TempJob),
                Colliders = new NativeList <Collider>(0, Allocator.TempJob),
            }.Run();

            new BVHTreeWorld.InsertJob {
                Tree      = world.tree,
                Bodies    = world.bodies,
                Colliders = colliders,
            }.Run();

            var until = Time.time + 30;

            // Prep raycast
            var rayResult  = new NativeList <int>(64, Allocator.TempJob);
            var rayVisited = new NativeList <int>(64, Allocator.TempJob);
            var ray        = new NativeBVHTree.Ray {
                origin      = new float3(-30, -30, 0),
                direction   = math.normalize(new float3(5, 5, 5)),
                minDistance = 0,
                maxDistance = 500
            };
            // Job
            var job = new RaycastJob {
                Tree    = world.tree,
                Ray     = ray,
                Results = rayResult,
            };

            for (var i = 0; i < world.bodies.Length; i++)
            {
                movingObjects.Add(new MovingObject {
                    transform = RigidTransform.identity,
                    velocity  = new float3(Random.Range(-1f, 1f), Random.Range(-1f, 1f), Random.Range(-1f, 1f))
                });
            }

            while (Time.time < until)
            {
                // Update
                Profiler.BeginSample("BVH - World.Update");
                world.Update();
                Profiler.EndSample();
                Profiler.BeginSample("BVH - Raycast");
                job.Run();
                Profiler.EndSample();
                yield return(null);

                for (var i = 0; i < world.bodies.Length; i++)
                {
                    // Update position
                    var movingObject = movingObjects[i];
                    movingObject.transform.pos += movingObject.velocity * Time.deltaTime * 2;
                    movingObjects[i]            = movingObject;
                    // And update world
                    world.UpdateTransform(i, movingObject.transform);
                }

                // Debug
                NativeBVHDebugDrawer.LastTree           = world.tree;
                NativeBVHDebugDrawer.LastTreeHits       = rayResult.ToArray();
                NativeBVHDebugDrawer.LastTreeRayVisited = new bool[world.tree.DebugGetTotalNodesLength() + 1];
                foreach (var i in rayVisited)
                {
                    NativeBVHDebugDrawer.LastTreeRayVisited[i] = true;
                }
                NativeBVHDebugDrawer.LastRay = ray;
            }
        }