// Raycasting, processing the leg's position
            // 脚位置的计算器. 主要是看 IKPosition 和 IKRotation怎么计算的
            public void Process()
            {
                if (!initiated)
                {
                    return;
                }
                if (grounding.maxStep <= 0)
                {
                    return;
                }

                deltaTime = Time.time - lastTime;
                lastTime  = Time.time;
                if (deltaTime == 0f)
                {
                    return;
                }

                up = grounding.up;
                heightFromGround = Mathf.Infinity;

                // Calculating velocity
                velocity = (transform.position - lastPosition) / deltaTime;
                //速度投影到适合地面的方向(平行?)
                velocity     = grounding.Flatten(velocity);
                lastPosition = transform.position;

                Vector3 prediction = velocity * grounding.prediction;

                if (grounding.footRadius <= 0)
                {
                    grounding.quality = Grounding.Quality.Fastest;
                }

                // Raycasting
                switch (grounding.quality)
                {
                // The fastest, single raycast
                case Grounding.Quality.Fastest:

                    RaycastHit predictedHit = GetRaycastHit(prediction);
                    SetFootToPoint(predictedHit.normal, predictedHit.point);
                    break;

                // Medium, 3 raycasts
                case Grounding.Quality.Simple:

                    heelHit = GetRaycastHit(Vector3.zero);
                    Vector3 f = grounding.GetFootCenterOffset();
                    if (invertFootCenter)
                    {
                        f = -f;
                    }
                    RaycastHit toeHit  = GetRaycastHit(f + prediction);
                    RaycastHit sideHit = GetRaycastHit(grounding.root.right * grounding.footRadius * 0.5f);

                    Vector3 planeNormal = Vector3.Cross(toeHit.point - heelHit.point, sideHit.point - heelHit.point).normalized;
                    if (Vector3.Dot(planeNormal, up) < 0)
                    {
                        planeNormal = -planeNormal;
                    }

                    SetFootToPlane(planeNormal, heelHit.point, heelHit.point);
                    break;

                // The slowest, raycast and a capsule cast
                case Grounding.Quality.Best:
                    heelHit = GetRaycastHit(invertFootCenter? -grounding.GetFootCenterOffset(): Vector3.zero);
                    RaycastHit capsuleHit = GetCapsuleHit(prediction);

                    SetFootToPlane(capsuleHit.normal, capsuleHit.point, heelHit.point);
                    break;
                }


                // Is the foot grounded?
                isGrounded = heightFromGround < grounding.maxStep;

                //获取脚离地的高度. stepHeightFromGround 值是通过:脚上的射线获得 脚transform.position,再 脚transform.position - root.tranform.position
                float offsetTarget = stepHeightFromGround;

                //若不在地面上,这个高度置0
                if (!grounding.rootGrounded)
                {
                    offsetTarget = 0f;
                }

                //脚步IK偏移计算: 线性插值的方式. 将偏移值逐渐修改至离地的高度
                IKOffset = Interp.LerpValue(IKOffset, offsetTarget, grounding.footSpeed, grounding.footSpeed);
                //脚步IK偏移计算: 跟上面的差不多.不知道为啥要用两个
                IKOffset = Mathf.Lerp(IKOffset, offsetTarget, deltaTime * grounding.footSpeed);

                //获取脚离地的实际高度
                float legHeight = grounding.GetVerticalOffset(transform.position, grounding.root.position);
                // 当前脚的高度距离最大离地距离还差多少高度
                float currentMaxOffset = Mathf.Clamp(grounding.maxStep - legHeight, 0f, grounding.maxStep);

                // 限制(在阶梯处会一直脚高一直脚低)
                IKOffset = Mathf.Clamp(IKOffset, -currentMaxOffset, IKOffset);

                RotateFoot();
                // Update IK values
                IKPosition = transform.position - up * IKOffset;

                float rW = grounding.footRotationWeight;

                rotationOffset = rW >= 1? r: Quaternion.Slerp(Quaternion.identity, r, rW);
            }
Beispiel #2
0
            // Raycasting, processing the leg's position
            public void Process()
            {
                if (!initiated)
                {
                    return;
                }
                if (grounding.maxStep <= 0)
                {
                    return;
                }

                transformPosition      = doOverrideFootPosition ? overrideFootPosition : transform.position;
                doOverrideFootPosition = false;

                deltaTime = Time.time - lastTime;
                lastTime  = Time.time;
                if (deltaTime == 0f)
                {
                    return;
                }

                up = grounding.up;
                heightFromGround = Mathf.Infinity;

                // Calculating velocity
                velocity     = (transformPosition - lastPosition) / deltaTime;
                velocity     = grounding.Flatten(velocity);
                lastPosition = transformPosition;

                Vector3 prediction = velocity * grounding.prediction;

                if (grounding.footRadius <= 0)
                {
                    grounding.quality = Grounding.Quality.Fastest;
                }

                // Raycasting
                switch (grounding.quality)
                {
                // The fastest, single raycast
                case Grounding.Quality.Fastest:

                    RaycastHit predictedHit = GetRaycastHit(prediction);
                    SetFootToPoint(predictedHit.normal, predictedHit.point);
                    break;

                // Medium, 3 raycasts
                case Grounding.Quality.Simple:

                    heelHit = GetRaycastHit(Vector3.zero);
                    Vector3 f = grounding.GetFootCenterOffset();
                    if (invertFootCenter)
                    {
                        f = -f;
                    }
                    RaycastHit toeHit  = GetRaycastHit(f + prediction);
                    RaycastHit sideHit = GetRaycastHit(grounding.root.right * grounding.footRadius * 0.5f);

                    Vector3 planeNormal = Vector3.Cross(toeHit.point - heelHit.point, sideHit.point - heelHit.point).normalized;
                    if (Vector3.Dot(planeNormal, up) < 0)
                    {
                        planeNormal = -planeNormal;
                    }

                    SetFootToPlane(planeNormal, heelHit.point, heelHit.point);
                    break;

                // The slowest, raycast and a capsule cast
                case Grounding.Quality.Best:
                    heelHit    = GetRaycastHit(invertFootCenter? -grounding.GetFootCenterOffset(): Vector3.zero);
                    capsuleHit = GetCapsuleHit(prediction);

                    SetFootToPlane(capsuleHit.normal, capsuleHit.point, heelHit.point);
                    break;
                }

                // Is the foot grounded?
                isGrounded = heightFromGround < grounding.maxStep;

                float offsetTarget = stepHeightFromGround;

                if (!grounding.rootGrounded)
                {
                    offsetTarget = 0f;
                }

                IKOffset = Interp.LerpValue(IKOffset, offsetTarget, grounding.footSpeed, grounding.footSpeed);
                IKOffset = Mathf.Lerp(IKOffset, offsetTarget, deltaTime * grounding.footSpeed);

                float legHeight        = grounding.GetVerticalOffset(transformPosition, grounding.root.position);
                float currentMaxOffset = Mathf.Clamp(grounding.maxStep - legHeight, 0f, grounding.maxStep);

                IKOffset = Mathf.Clamp(IKOffset, -currentMaxOffset, IKOffset);

                RotateFoot();

                // Update IK values
                IKPosition = transformPosition - up * IKOffset;

                float rW = grounding.footRotationWeight;

                rotationOffset = rW >= 1? r: Quaternion.Slerp(Quaternion.identity, r, rW);
            }