/// <summary>
    /// 需要unsafe来使用指针
    /// </summary>
    protected unsafe override JobHandle OnUpdate(JobHandle inputDependencies)
    {
        var physicsWorld = m_BuildPhysicsWorldSystem.PhysicsWorld;
        var time         = m_GameTimeSingletonQuery.GetSingleton <GlobalGameTime>().gameTime;
        //var predictingTick = World.GetExistingSystem<GhostPredictionSystemGroup>().PredictingTick; 预测

        var constraints = new NativeList <SurfaceConstraintInfo>(Allocator.Temp); //表面约束信息?
        var castHits    = new NativeList <ColliderCastHit>(Allocator.Temp);       //射线击中信息?

        var deltaTime = Time.DeltaTime;

        Entities
        .WithName("CheckSupportJob")
        .ForEach((
                     ref CharacterControllerComponentData ccData,
                     ref CharacterControllerMoveQuery ccQuery,
                     ref CharacterControllerMoveResult resultPosition,
                     ref CharacterControllerVelocity velocity,
                     ref CharacterControllerCollider ccCollider,
                     ref CharacterControllerGroundSupportData ccGroundData
                     //in PredictedGhostComponent predictedGhostComponent
                     ) => {
            //if(!GhostPredictionSystemGroup.ShouldPredict(PredictingTick,predictedGhostComponent))
            //    return;

            //查询到的信息写入状态信息
            if (!ccQuery.CheckSupport)
            {
                ccGroundData.SupportedState  = CharacterControllerUtilities.CharacterSupportState.Unsupported;
                ccGroundData.SurfaceVelocity = float3.zero;
                ccGroundData.SurfaceNormal   = float3.zero;
            }

            constraints.Clear();
            castHits.Clear();

            var collider = (Unity.Physics.Collider *)ccCollider.Collider.GetUnsafePtr();

            var stepInput = new CharacterControllerUtilities.CharacterControllerStepInput {
                World = physicsWorld,
                //DeltaTime = time.tickInterval,
                DeltaTime        = deltaTime,
                Up               = math.up(),//设定角色永远头朝上
                Gravity          = new float3(0.0f, -9.8f, 0.0f),
                MaxIterations    = ccData.MaxIterations,
                Tau              = CharacterControllerUtilities.k_DefaultTau,
                Damping          = CharacterControllerUtilities.k_DefaultDamping,
                SkinWidth        = ccData.SkinWidth,
                ContactTolerance = ccData.ContactTolearance * 2.0f,
                MaxSlope         = ccData.MaxSlope,
                RigidBodyIndex   = -1,
                CurrentVelocity  = velocity.WorldVelocity,
                MaxMovementSpeed = ccData.MaxMovementSpeed
            };

            var transform = new RigidTransform {
                pos = resultPosition.MoveResult,
                rot = quaternion.identity
            };
            //FollowGround为了解决上下坡穿入的问题
            float probeFactor = ccQuery.FollowGroud ? 2 : 1;

            CharacterControllerUtilities.CheckSupport(
                ref physicsWorld,
                collider,
                stepInput,
                ccData.GroundProbeVector * probeFactor,
                transform,
                ccData.MaxSlope,
                ref constraints,
                ref castHits,
                out ccGroundData.SupportedState,
                out ccGroundData.SurfaceNormal,
                out ccGroundData.SurfaceVelocity);
        }).Run();


        constraints.Dispose();
        castHits.Dispose();

        return(inputDependencies);
    }
    protected unsafe override JobHandle OnUpdate(JobHandle inputDeps)
    {
        var physicsWorld   = m_BuildPhysicsWorldSystem.PhysicsWorld;
        var time           = m_GameTimeSingletonQuery.GetSingleton <GlobalGameTime>().gameTime;
        var PredictingTick = World.GetExistingSystem <GhostPredictionSystemGroup>().PredictingTick;

        var constraints = new NativeList <SurfaceConstraintInfo>(Allocator.Temp);
        var castHits    = new NativeList <ColliderCastHit>(Allocator.Temp);

        Entities
        .WithName("CheckSupportJob")
        .ForEach((
                     ref CharacterControllerComponentData ccData,
                     ref CharacterControllerMoveQuery ccQuery,
                     ref CharacterControllerMoveResult resultPosition,
                     ref CharacterControllerVelocity velocity,
                     ref CharacterControllerCollider ccCollider,
                     ref CharacterControllerGroundSupportData ccGroundData,
                     in PredictedGhostComponent predictedGhostComponent) =>
        {
            if (!GhostPredictionSystemGroup.ShouldPredict(PredictingTick, predictedGhostComponent))
            {
                return;
            }

            if (!ccQuery.CheckSupport)
            {
                ccGroundData.SupportedState  = CharacterControllerUtilities.CharacterSupportState.Unsupported;
                ccGroundData.SurfaceVelocity = float3.zero;
                ccGroundData.SurfaceNormal   = float3.zero;
                return;
            }

            constraints.Clear();
            castHits.Clear();

            var collider = (Unity.Physics.Collider *)ccCollider.Collider.GetUnsafePtr();

            var stepInput = new CharacterControllerUtilities.CharacterControllerStepInput
            {
                World            = physicsWorld,
                DeltaTime        = time.tickInterval,
                Up               = math.up(),
                Gravity          = new float3(0.0f, -9.8f, 0.0f),
                MaxIterations    = ccData.MaxIterations,
                Tau              = CharacterControllerUtilities.k_DefaultTau,
                Damping          = CharacterControllerUtilities.k_DefaultDamping,
                SkinWidth        = ccData.SkinWidth,
                ContactTolerance = ccData.ContactTolerance * 2.0f,
                MaxSlope         = ccData.MaxSlope,
                RigidBodyIndex   = -1,
                CurrentVelocity  = velocity.Velocity,
                MaxMovementSpeed = ccData.MaxMovementSpeed
            };

            var transform = new RigidTransform
            {
                pos = resultPosition.MoveResult,
                rot = quaternion.identity
            };

            // FollowGround can cause the collider to lift further above ground
            // before entering upwards slopes or exiting downwards slopes.
            // Halfpipes show the issue the most.
            // Lengthen the ground probe vector to remove undesired unsupporteds.
            float probeFactor = ccQuery.FollowGround ? 2 : 1;

            // Check support
            CharacterControllerUtilities.CheckSupport(
                ref physicsWorld,
                collider,
                stepInput,
                ccData.GroundProbeVector * probeFactor,
                transform,
                ccData.MaxSlope,
                ref constraints,
                ref castHits,
                out ccGroundData.SupportedState,
                out ccGroundData.SurfaceNormal,
                out ccGroundData.SurfaceVelocity);
        }).Run();

        constraints.Dispose();
        castHits.Dispose();

        return(inputDeps);
    }
    protected unsafe override JobHandle OnUpdate(JobHandle inputDeps)
    {
        var physicsWorld   = m_BuildPhysicsWorldSystem.PhysicsWorld;
        var time           = m_GameTimeSingletonQuery.GetSingleton <GlobalGameTime>().gameTime;
        var PredictingTick = World.GetExistingSystem <GhostPredictionSystemGroup>().PredictingTick;

        Entities
        .WithName("CheckSupportJob")
        .ForEach((
                     ref CharacterControllerComponentData ccData,
                     ref CharacterControllerMoveQuery ccQuery,
                     ref CharacterControllerMoveResult resultPosition,
                     ref CharacterControllerVelocity velocity,
                     ref CharacterControllerCollider ccCollider,
                     ref CharacterControllerGroundSupportData ccGroundData,
                     in PredictedGhostComponent predictedGhostComponent) =>
        {
            if (!GhostPredictionSystemGroup.ShouldPredict(PredictingTick, predictedGhostComponent))
            {
                return;
            }

            if (!ccQuery.CheckSupport)
            {
                ccGroundData.SupportedState  = CharacterControllerUtilities.CharacterSupportState.Unsupported;
                ccGroundData.SurfaceVelocity = float3.zero;
                ccGroundData.SurfaceNormal   = float3.zero;
                return;
            }

            var stepInput = new CharacterControllerUtilities.CharacterControllerStepInput
            {
                World            = physicsWorld,
                DeltaTime        = time.tickDuration,
                Up               = math.up(),
                Gravity          = new float3(0.0f, -9.8f, 0.0f),
                MaxIterations    = ccData.MaxIterations,
                Tau              = 0.4f, // CharacterControllerUtilities.k_DefaultTau,
                Damping          = 0.9f, // CharacterControllerUtilities.k_DefaultDamping,
                SkinWidth        = ccData.SkinWidth,
                ContactTolerance = ccData.ContactTolerance * 2.0f,
                MaxSlope         = ccData.MaxSlope,
                RigidBodyIndex   = -1,
                CurrentVelocity  = velocity.Velocity,
                MaxMovementSpeed = ccData.MaxMovementSpeed
            };

            var transform = new RigidTransform
            {
                pos = resultPosition.MoveResult,
                rot = quaternion.identity
            };

            var collider = (Unity.Physics.Collider *)ccCollider.Collider.GetUnsafePtr();

            // FollowGround can cause the collider to lift further above ground
            // before entering upwards slopes or exiting downwards slopes.
            // Halfpipes show the issue the most.
            // Lengthen the ground probe vector to remove undesired unsupporteds.
            float probeFactor = ccQuery.FollowGround ? 2 : 1;
            // Check support
            CharacterControllerUtilities.CheckSupport(
                ref physicsWorld,
                collider,
                stepInput,
                transform,
                out ccGroundData.SupportedState,
                out ccGroundData.SurfaceNormal,
                out ccGroundData.SurfaceVelocity);

            //for (int i = 0; i < constraints.Length; i++)
            //{
            //    var constraint = constraints[i];
            //    DebugDraw.Line(constraint.HitPosition, constraint.HitPosition + constraint.Plane.Normal, constraint.Touched && !constraint.IsTooSteep ? UnityEngine.Color.blue : UnityEngine.Color.red);
            //    DebugDraw.Sphere(constraint.HitPosition, 0.1f, constraint.IsTooSteep ? UnityEngine.Color.blue : UnityEngine.Color.red);
            //    DebugDraw.Circle(constraint.HitPosition, math.up(), 0.2f, constraint.Touched ? UnityEngine.Color.blue : UnityEngine.Color.red);
            //    //DebugDraw.Arrow(constraint.HitPosition, 30f, constraint.Plane.Distance > 0 ? UnityEngine.Color.blue : UnityEngine.Color.red);
            //    //GameDebug.Log($"constraints.dis {constraint.Plane.Distance}");
            //}
            //Unity.Sample.Core.GameDebug.Log($"--- constraints: {numSupportingPlanes}");
            //Unity.Sample.Core.GameDebug.Log($"2 groundState.SurfaceVelocity {ccGroundData.SurfaceVelocity}");
        }).Run();


        return(inputDeps);
    }
    protected unsafe override JobHandle OnUpdate(JobHandle inputDeps)
    {
        var entityCount = m_CharacterControllerGroup.CalculateEntityCount();

        if (entityCount == 0)
        {
            return(inputDeps);
        }

        var defferredImpulses = new NativeStream(entityCount, Allocator.TempJob);
        var time        = m_TimeSingletonQuery.GetSingleton <GlobalGameTime>().gameTime;
        var physicWorld = m_BuildPhysicsWorld.PhysicsWorld;

        var writer = defferredImpulses.AsWriter();

        var constraints  = new NativeList <SurfaceConstraintInfo>(Allocator.Temp);
        var castHits     = new NativeList <ColliderCastHit>(Allocator.Temp);
        var distanceHits = new NativeList <DistanceHit>(Allocator.Temp);

        var input  = new ColliderCastInput();
        var hit    = new ColliderCastHit();
        var hasHit = false;

        var deltaTime = Time.DeltaTime;

        Entities
        .WithName("CharacterControllerStepSystem")
        .ForEach((
                     ref CharacterControllerComponentData ccData,
                     ref CharacterControllerCollider ccCollider,
                     ref CharacterControllerMoveQuery moveQuery,
                     ref CharacterControllerMoveResult moveResult,
                     ref CharacterControllerVelocity velocity
                     ) => {
            var collider = (Collider *)ccCollider.Collider.GetUnsafePtr();

            var stepInput = new CharacterControllerUtilities.CharacterControllerStepInput {
                World = physicWorld,
                //DeltaTime = time.tickDuration,
                DeltaTime        = deltaTime,
                Gravity          = new float3(0.0f, -9.8f, 0.0f),
                MaxIterations    = ccData.MaxIterations,
                Tau              = CharacterControllerUtilities.k_DefaultTau,
                Damping          = CharacterControllerUtilities.k_DefaultDamping,
                SkinWidth        = ccData.SkinWidth,
                ContactTolerance = ccData.ContactTolearance,
                MaxSlope         = ccData.MaxSlope,
                RigidBodyIndex   = -1,
                CurrentVelocity  = velocity.WorldVelocity,
                MaxMovementSpeed = ccData.MaxMovementSpeed,
                FollowGroud      = moveQuery.FollowGroud
            };

            var transform = new RigidTransform {
                pos = moveQuery.StartPosition,
                rot = quaternion.identity
            };

            CharacterControllerUtilities.CollideAndIntegrate(
                stepInput,
                ccData.CharacterMass,
                ccData.AffectsPhysicsBodies > 0,
                collider,
                ref transform,
                ref velocity.WorldVelocity,
                ref writer,
                ref constraints,
                ref castHits,
                ref distanceHits,
                out input,
                out hit);

            moveResult.MoveResult = transform.pos;
        })
        .Run();


        var applyJob = new ApplyDefferedImpulses()
        {
            DeferredImpulseReader = defferredImpulses.AsReader(),
            PhysicsVelocityData   = GetComponentDataFromEntity <PhysicsVelocity>(),
            PhysicsMassData       = GetComponentDataFromEntity <PhysicsMass>(),
            TranslationData       = GetComponentDataFromEntity <Translation>(),
            RotationData          = GetComponentDataFromEntity <Rotation>()
        };

        applyJob.Run();

        CharacterControllerDebug.input = input;
        CharacterControllerDebug.hit   = hit;

        defferredImpulses.Dispose();
        constraints.Dispose();
        castHits.Dispose();
        distanceHits.Dispose();

        return(inputDeps);
    }