暂无描述
您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

CCD2D.cs 2.5KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061
  1. using UnityEngine.Scripting.APIUpdating;
  2. namespace UnityEngine.U2D.IK
  3. {
  4. /// <summary>
  5. /// Utility for 2D based Cyclic Coordinate Descent (CCD) IK Solver.
  6. /// </summary>
  7. [MovedFrom("UnityEngine.Experimental.U2D.IK")]
  8. public static class CCD2D
  9. {
  10. /// <summary>
  11. /// Solve IK Chain based on CCD.
  12. /// </summary>
  13. /// <param name="targetPosition">Target position.</param>
  14. /// <param name="forward">Forward vector for solver.</param>
  15. /// <param name="solverLimit">Solver iteration count.</param>
  16. /// <param name="tolerance">Target position's tolerance.</param>
  17. /// <param name="velocity">Velocity towards target position.</param>
  18. /// <param name="positions">Chain positions.</param>
  19. /// <returns>Returns true if solver successfully completes within iteration limit. False otherwise.</returns>
  20. public static bool Solve(Vector3 targetPosition, Vector3 forward, int solverLimit, float tolerance, float velocity, ref Vector3[] positions)
  21. {
  22. var last = positions.Length - 1;
  23. var iterations = 0;
  24. var sqrTolerance = tolerance * tolerance;
  25. var sqrDistanceToTarget = (targetPosition - positions[last]).sqrMagnitude;
  26. while (sqrDistanceToTarget > sqrTolerance)
  27. {
  28. DoIteration(targetPosition, forward, last, velocity, ref positions);
  29. sqrDistanceToTarget = (targetPosition - positions[last]).sqrMagnitude;
  30. if (++iterations >= solverLimit)
  31. break;
  32. }
  33. return iterations != 0;
  34. }
  35. static void DoIteration(Vector3 targetPosition, Vector3 forward, int last, float velocity, ref Vector3[] positions)
  36. {
  37. for (var i = last - 1; i >= 0; --i)
  38. {
  39. var toTarget = targetPosition - positions[i];
  40. var toLast = positions[last] - positions[i];
  41. var angle = Vector3.SignedAngle(toLast, toTarget, forward);
  42. angle = Mathf.Lerp(0f, angle, velocity);
  43. var deltaRotation = Quaternion.AngleAxis(angle, forward);
  44. for (var j = last; j > i; --j)
  45. positions[j] = RotatePositionFrom(positions[j], positions[i], deltaRotation);
  46. }
  47. }
  48. static Vector3 RotatePositionFrom(Vector3 position, Vector3 pivot, Quaternion rotation)
  49. {
  50. var v = position - pivot;
  51. v = rotation * v;
  52. return pivot + v;
  53. }
  54. }
  55. }