No Description
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

CCDSolver2D.cs 4.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. using System.Collections.Generic;
  2. using UnityEngine.Profiling;
  3. using UnityEngine.Scripting.APIUpdating;
  4. namespace UnityEngine.U2D.IK
  5. {
  6. /// <summary>
  7. /// Component responsible for 2D Cyclic Coordinate Descent (CCD) IK.
  8. /// </summary>
  9. [MovedFrom("UnityEngine.Experimental.U2D.IK")]
  10. [Solver2DMenuAttribute("Chain (CCD)")]
  11. [IconAttribute(IconUtility.IconPath + "Animation.IKCCD.png")]
  12. public sealed class CCDSolver2D : Solver2D
  13. {
  14. const int k_MinIterations = 1;
  15. const float k_MinTolerance = 0.001f;
  16. const float k_MinVelocity = 0.01f;
  17. const float k_MaxVelocity = 1f;
  18. [SerializeField]
  19. IKChain2D m_Chain = new IKChain2D();
  20. [SerializeField]
  21. [Range(k_MinIterations, 50)]
  22. int m_Iterations = 10;
  23. [SerializeField]
  24. [Range(k_MinTolerance, 0.1f)]
  25. float m_Tolerance = 0.01f;
  26. [SerializeField]
  27. [Range(0f, 1f)]
  28. float m_Velocity = 0.5f;
  29. Vector3[] m_Positions;
  30. /// <summary>
  31. /// Get and set the solver's integration count.
  32. /// </summary>
  33. public int iterations
  34. {
  35. get => m_Iterations;
  36. set => m_Iterations = Mathf.Max(value, k_MinIterations);
  37. }
  38. /// <summary>
  39. /// Get and set target distance tolerance.
  40. /// </summary>
  41. public float tolerance
  42. {
  43. get => m_Tolerance;
  44. set => m_Tolerance = Mathf.Max(value, k_MinTolerance);
  45. }
  46. /// <summary>
  47. /// Get and Set the solver velocity.
  48. /// </summary>
  49. public float velocity
  50. {
  51. get => m_Velocity;
  52. set => m_Velocity = Mathf.Clamp01(value);
  53. }
  54. /// <summary>
  55. /// Returns the number of chains in the solver.
  56. /// </summary>
  57. /// <returns>Returns 1, because CCD Solver has only one chain.</returns>
  58. protected override int GetChainCount() => 1;
  59. /// <summary>
  60. /// Gets the chain in the solver at index.
  61. /// </summary>
  62. /// <param name="index">Index to query. Not used in this override.</param>
  63. /// <returns>Returns IKChain2D for the Solver.</returns>
  64. public override IKChain2D GetChain(int index) => m_Chain;
  65. /// <summary>
  66. /// Prepares the data required for updating the solver.
  67. /// </summary>
  68. protected override void DoPrepare()
  69. {
  70. if (m_Positions == null || m_Positions.Length != m_Chain.transformCount)
  71. m_Positions = new Vector3[m_Chain.transformCount];
  72. var root = m_Chain.rootTransform;
  73. for (var i = 0; i < m_Chain.transformCount; ++i)
  74. m_Positions[i] = root.TransformPoint((Vector2)root.InverseTransformPoint(m_Chain.transforms[i].position));
  75. }
  76. /// <summary>
  77. /// Updates the IK and sets the chain's transform positions.
  78. /// </summary>
  79. /// <param name="targetPositions">Target positions for the chain.</param>
  80. protected override void DoUpdateIK(List<Vector3> targetPositions)
  81. {
  82. Profiler.BeginSample(nameof(CCDSolver2D.DoUpdateIK));
  83. var root = m_Chain.rootTransform;
  84. var targetPosition = targetPositions[0];
  85. var targetLocalPosition2D = (Vector2)root.InverseTransformPoint(targetPosition);
  86. targetPosition = root.TransformPoint(targetLocalPosition2D);
  87. if (CCD2D.Solve(targetPosition, GetPlaneRootTransform().forward, iterations, tolerance, Mathf.Lerp(k_MinVelocity, k_MaxVelocity, m_Velocity), ref m_Positions))
  88. {
  89. for (var i = 0; i < m_Chain.transformCount - 1; ++i)
  90. {
  91. var startLocalPosition = (Vector2)m_Chain.transforms[i + 1].localPosition;
  92. var endLocalPosition = (Vector2)m_Chain.transforms[i].InverseTransformPoint(m_Positions[i + 1]);
  93. m_Chain.transforms[i].localRotation *= Quaternion.AngleAxis(Vector2.SignedAngle(startLocalPosition, endLocalPosition), Vector3.forward);
  94. }
  95. }
  96. Profiler.EndSample();
  97. }
  98. }
  99. }