static void Rotate(float deltaSeconds, LocalToWorld destinationSurfaceLocalToWorld, LocalToWorld surfaceLocalToWorld, NavSteering steering, NavAgent agent, Translation translation, ref Rotation rotation)
        {
            var lookAt = (translation.Value + steering.CurrentHeading)
                         .ToWorld(destinationSurfaceLocalToWorld)
                         .ToLocal(surfaceLocalToWorld);

            lookAt.y = translation.Value.y;

            var lookRotation = quaternion.LookRotationSafe(lookAt - translation.Value, math.up());

            if (math.length(agent.SurfacePointNormal) > 0.01f)
            {
                lookRotation = math.mul(lookRotation, math.up().FromToRotation(agent.SurfacePointNormal));
            }

            rotation.Value = math.slerp(rotation.Value, lookRotation, deltaSeconds / agent.RotationSpeed);
        }
        static void HandleCompletePath(ComponentDataFromEntity <LocalToWorld> localToWorldFromEntity, Entity entity, Rotation rotation, ref NavAgent agent, Parent surface, Translation translation, PhysicsWorld physicsWorld, float elapsedSeconds, EntityCommandBuffer.ParallelWriter commandBuffer, int entityInQueryIndex, NavSettings settings)
        {
            var rayInput = new RaycastInput
            {
                Start  = localToWorldFromEntity[entity].Position + agent.Offset,
                End    = math.forward(rotation.Value) * settings.ObstacleRaycastDistanceMax,
                Filter = new CollisionFilter
                {
                    BelongsTo    = NavUtil.ToBitMask(settings.ColliderLayer),
                    CollidesWith = NavUtil.ToBitMask(settings.ObstacleLayer)
                }
            };

            if (
                !surface.Value.Equals(agent.DestinationSurface) &&
                !NavUtil.ApproxEquals(translation.Value, agent.LocalDestination, settings.StoppingDistance) &&
                !physicsWorld.CastRay(rayInput, out _)
                )
            {
                agent.JumpSeconds = elapsedSeconds;

                commandBuffer.RemoveComponent <NavWalking>(entityInQueryIndex, entity);
                commandBuffer.RemoveComponent <NavSteering>(entityInQueryIndex, entity);
                commandBuffer.AddComponent <NavJumping>(entityInQueryIndex, entity);
                commandBuffer.AddComponent <NavPlanning>(entityInQueryIndex, entity);

                return;
            }

            commandBuffer.RemoveComponent <NavWalking>(entityInQueryIndex, entity);
            commandBuffer.RemoveComponent <NavSteering>(entityInQueryIndex, entity);
            commandBuffer.RemoveComponent <NavDestination>(entityInQueryIndex, entity);
        }
 static void Translate(float deltaSeconds, NavSteering steering, NavAgent agent, ref Translation translation)
 => translation.Value += steering.CurrentHeading * agent.TranslationSpeed * deltaSeconds;