// 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); }
// 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); }