CCDSolver2D.cs 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. using System.Collections.Generic;
  2. using UnityEngine.Profiling;
  3. using UnityEngine.Scripting.APIUpdating;
  4. namespace UnityEngine.U2D.IK
  5. {
  6. /// <summary>
  7. /// Component for 2D Cyclic Coordinate Descent (CCD) IK.
  8. /// </summary>
  9. [MovedFrom("UnityEngine.Experimental.U2D.IK")]
  10. [Solver2DMenuAttribute("Chain (CCD)")]
  11. public class CCDSolver2D : Solver2D
  12. {
  13. private const float kMinTolerance = 0.001f;
  14. private const int kMinIterations = 1;
  15. private const float kMinVelocity = 0.01f;
  16. private const float kMaxVelocity = 1f;
  17. [SerializeField]
  18. private IKChain2D m_Chain = new IKChain2D();
  19. [SerializeField][Range(kMinIterations, 50)]
  20. private int m_Iterations = 10;
  21. [SerializeField][Range(kMinTolerance, 0.1f)]
  22. private float m_Tolerance = 0.01f;
  23. [SerializeField][Range(0f, 1f)]
  24. private float m_Velocity = 0.5f;
  25. private Vector3[] m_Positions;
  26. /// <summary>
  27. /// Get and Set the solver's itegration count.
  28. /// </summary>
  29. public int iterations
  30. {
  31. get { return m_Iterations; }
  32. set { m_Iterations = Mathf.Max(value, kMinIterations); }
  33. }
  34. /// <summary>
  35. /// Get and Set target distance tolerance.
  36. /// </summary>
  37. public float tolerance
  38. {
  39. get { return m_Tolerance; }
  40. set { m_Tolerance = Mathf.Max(value, kMinTolerance); }
  41. }
  42. /// <summary>
  43. /// Get and Set the solver velocity.
  44. /// </summary>
  45. public float velocity
  46. {
  47. get { return m_Velocity; }
  48. set { m_Velocity = Mathf.Clamp01(value); }
  49. }
  50. /// <summary>
  51. /// Returns the number of chain in the solver.
  52. /// </summary>
  53. /// <returns>This always returns 1</returns>
  54. protected override int GetChainCount()
  55. {
  56. return 1;
  57. }
  58. /// <summary>
  59. /// Gets the chain in the solver by index.
  60. /// </summary>
  61. /// <param name="index">Chain index.</param>
  62. /// <returns>Returns IKChain2D at the index.</returns>
  63. public override IKChain2D GetChain(int index)
  64. {
  65. return m_Chain;
  66. }
  67. /// <summary>
  68. /// DoPrepare override from base class.
  69. /// </summary>
  70. protected override void DoPrepare()
  71. {
  72. if (m_Positions == null || m_Positions.Length != m_Chain.transformCount)
  73. m_Positions = new Vector3[m_Chain.transformCount];
  74. for (int i = 0; i < m_Chain.transformCount; ++i)
  75. m_Positions[i] = m_Chain.transforms[i].position;
  76. }
  77. /// <summary>
  78. /// DoUpdateIK override from base class.
  79. /// </summary>
  80. /// <param name="effectorPositions">Target position for the chain.</param>
  81. protected override void DoUpdateIK(List<Vector3> effectorPositions)
  82. {
  83. Profiler.BeginSample("CCDSolver2D.DoUpdateIK");
  84. Vector3 effectorPosition = effectorPositions[0];
  85. Vector2 effectorLocalPosition2D = m_Chain.transforms[0].InverseTransformPoint(effectorPosition);
  86. effectorPosition = m_Chain.transforms[0].TransformPoint(effectorLocalPosition2D);
  87. if (CCD2D.Solve(effectorPosition, GetPlaneRootTransform().forward, iterations, tolerance, Mathf.Lerp(kMinVelocity, kMaxVelocity, m_Velocity), ref m_Positions))
  88. {
  89. for (int i = 0; i < m_Chain.transformCount - 1; ++i)
  90. {
  91. Vector3 startLocalPosition = m_Chain.transforms[i + 1].localPosition;
  92. Vector3 endLocalPosition = m_Chain.transforms[i].InverseTransformPoint(m_Positions[i + 1]);
  93. m_Chain.transforms[i].localRotation *= Quaternion.FromToRotation(startLocalPosition, endLocalPosition);
  94. }
  95. }
  96. Profiler.EndSample();
  97. }
  98. }
  99. }