protected override JobHandle OnUpdate(JobHandle inputDeps)
    {
        var  collisionHistory = m_physicsHistory.CollisionHistory;
        uint predictingTick   = m_predictionGroup.PredictingTick;

        // Do not perform hit-scan when rolling back, only when simulating the latest tick
        if (!m_predictionGroup.IsFinalPredictionTick)
        {
            return(inputDeps);
        }
        var isServer = m_IsServer;
        // Not using burst since there is a static used to update the UI
        var handle = Entities.WithoutBurst().ForEach((DynamicBuffer <RayTraceCommand> commands, in CommandDataInterpolationDelay delay) =>
        {
            // If there is no data for the tick or a fire was not requested - do not process anything
            if (!commands.GetDataAtTick(predictingTick, out var cmd))
            {
                return;
            }
            if (cmd.lastFire != predictingTick)
            {
                return;
            }

            // Get the collision world to use given the tick currently being predicted and the interpolation delay for the connection
            collisionHistory.GetCollisionWorldFromTick(predictingTick, LagUI.EnableLagCompensation ? delay.Delay : 0, out var collWorld);
            var rayInput    = new Unity.Physics.RaycastInput();
            rayInput.Start  = cmd.origin;
            rayInput.End    = cmd.origin + cmd.direction * 100;
            rayInput.Filter = Unity.Physics.CollisionFilter.Default;
            bool hit        = collWorld.CastRay(rayInput);
            if (isServer)
            {
                LagUI.ServerTick = predictingTick;
                LagUI.ServerHit  = hit;
            }
            else
            {
                LagUI.ClientTick = predictingTick;
                LagUI.ClientHit  = hit;
            }
        }).Schedule(JobHandle.CombineDependencies(inputDeps, m_physicsHistory.LastPhysicsJobHandle));

        m_physicsHistory.LastPhysicsJobHandle = handle;
        return(handle);
    }
    // This should be a job rather than happening on the main thread. However, it doesn't really take a long time, and happens infrequently.
    protected override void OnUpdate()
    {
        var physicsWorldSystem = World.Active.GetExistingSystem <Unity.Physics.Systems.BuildPhysicsWorld>();
        var collisionWorld     = physicsWorldSystem.PhysicsWorld.CollisionWorld;

        Entities.With(mRaycastRequestsQuery).ForEach((Entity entity, ref RayRequest r) =>
        {
            Unity.Physics.RaycastInput input = new Unity.Physics.RaycastInput()
            {
                Start  = r.Value.Origin,
                End    = r.Value.Displacement,
                Filter = Unity.Physics.CollisionFilter.Default,
            };

            Debug.DrawLine(input.Start, input.End, Color.blue, 0.5f);

            var hit = new Unity.Physics.RaycastHit();
            if (collisionWorld.CastRay(input, out hit))
            {
                var e = physicsWorldSystem.PhysicsWorld.Bodies[hit.RigidBodyIndex].Entity;
                if (EntityManager.HasComponent <IFCGuidUIPosition>(e))
                {
                    PostUpdateCommands.RemoveComponent <IFCGuidUIPosition>(e);
                    PostUpdateCommands.AddComponent <DeselectedTag>(e);
                }
                else
                {
                    PostUpdateCommands.AddComponent(e, new IFCGuidUIPosition {
                        Value = hit.Position
                    });
                }
            }

            PostUpdateCommands.DestroyEntity(entity);
        });
    }