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

FabrikSolver2D.cs 3.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  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 Forward And Backward Reaching Inverse Kinematics (FABRIK) IK.
  8. /// </summary>
  9. [MovedFrom("UnityEngine.Experimental.U2D.IK")]
  10. [Solver2DMenu("Chain (FABRIK)")]
  11. public class FabrikSolver2D : Solver2D
  12. {
  13. const float k_MinTolerance = 0.001f;
  14. const int k_MinIterations = 1;
  15. [SerializeField]
  16. IKChain2D m_Chain = new IKChain2D();
  17. [SerializeField]
  18. [Range(k_MinIterations, 50)]
  19. int m_Iterations = 10;
  20. [SerializeField]
  21. [Range(k_MinTolerance, 0.1f)]
  22. float m_Tolerance = 0.01f;
  23. float[] m_Lengths;
  24. Vector2[] m_Positions;
  25. Vector3[] m_WorldPositions;
  26. /// <summary>
  27. /// Get and Set the solver's integration count.
  28. /// </summary>
  29. public int iterations
  30. {
  31. get => m_Iterations;
  32. set => m_Iterations = Mathf.Max(value, k_MinIterations);
  33. }
  34. /// <summary>
  35. /// Get and Set target distance tolerance.
  36. /// </summary>
  37. public float tolerance
  38. {
  39. get => m_Tolerance;
  40. set => m_Tolerance = Mathf.Max(value, k_MinTolerance);
  41. }
  42. /// <summary>
  43. /// Returns the number of chain in the solver.
  44. /// </summary>
  45. /// <returns>This always returns 1.</returns>
  46. protected override int GetChainCount() => 1;
  47. /// <summary>
  48. /// Gets the chain in the solver by index.
  49. /// </summary>
  50. /// <param name="index">Chain index.</param>
  51. /// <returns>Returns IKChain2D at the index.</returns>
  52. public override IKChain2D GetChain(int index) => m_Chain;
  53. /// <summary>
  54. /// DoPrepare override from base class.
  55. /// </summary>
  56. protected override void DoPrepare()
  57. {
  58. if (m_Positions == null || m_Positions.Length != m_Chain.transformCount)
  59. {
  60. m_Positions = new Vector2[m_Chain.transformCount];
  61. m_Lengths = new float[m_Chain.transformCount - 1];
  62. m_WorldPositions = new Vector3[m_Chain.transformCount];
  63. }
  64. for (var i = 0; i < m_Chain.transformCount; ++i)
  65. {
  66. m_Positions[i] = GetPointOnSolverPlane(m_Chain.transforms[i].position);
  67. }
  68. for (var i = 0; i < m_Chain.transformCount - 1; ++i)
  69. {
  70. m_Lengths[i] = (m_Positions[i + 1] - m_Positions[i]).magnitude;
  71. }
  72. }
  73. /// <summary>
  74. /// DoUpdateIK override from base class.
  75. /// </summary>
  76. /// <param name="effectorPositions">Target position for the chain.</param>
  77. protected override void DoUpdateIK(List<Vector3> effectorPositions)
  78. {
  79. Profiler.BeginSample(nameof(FabrikSolver2D.DoUpdateIK));
  80. var effectorPosition = effectorPositions[0];
  81. effectorPosition = GetPointOnSolverPlane(effectorPosition);
  82. if (FABRIK2D.Solve(effectorPosition, iterations, tolerance, m_Lengths, ref m_Positions))
  83. {
  84. // Convert all plane positions to world positions
  85. for (var i = 0; i < m_Positions.Length; ++i)
  86. {
  87. m_WorldPositions[i] = GetWorldPositionFromSolverPlanePoint(m_Positions[i]);
  88. }
  89. for (var i = 0; i < m_Chain.transformCount - 1; ++i)
  90. {
  91. var startLocalPosition = m_Chain.transforms[i + 1].localPosition;
  92. var endLocalPosition = m_Chain.transforms[i].InverseTransformPoint(m_WorldPositions[i + 1]);
  93. m_Chain.transforms[i].localRotation *= Quaternion.FromToRotation(startLocalPosition, endLocalPosition);
  94. }
  95. }
  96. Profiler.EndSample();
  97. }
  98. }
  99. }