VRIK.cs 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. using UnityEngine;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. namespace RootMotion.FinalIK {
  5. /// <summary>
  6. /// A full-body IK solver designed specifically for a VR HMD and hand controllers.
  7. /// </summary>
  8. //[HelpURL("http://www.root-motion.com/finalikdox/html/page16.html")]
  9. [AddComponentMenu("Scripts/RootMotion.FinalIK/IK/VR IK")]
  10. public class VRIK : IK {
  11. /// <summary>
  12. /// VRIK-specific definition of a humanoid biped.
  13. /// </summary>
  14. [System.Serializable]
  15. public class References {
  16. public Transform root; // 0
  17. public Transform pelvis; // 1
  18. public Transform spine; // 2
  19. [Tooltip("Optional")]
  20. public Transform chest; // 3 Optional
  21. [Tooltip("Optional")]
  22. public Transform neck; // 4 Optional
  23. public Transform head; // 5
  24. [Tooltip("Optional")]
  25. public Transform leftShoulder; // 6 Optional
  26. public Transform leftUpperArm; // 7
  27. public Transform leftForearm; // 8
  28. public Transform leftHand; // 9
  29. [Tooltip("Optional")]
  30. public Transform rightShoulder; // 10 Optional
  31. public Transform rightUpperArm; // 11
  32. public Transform rightForearm; // 12
  33. public Transform rightHand; // 13
  34. [Tooltip("VRIK also supports legless characters.If you do not wish to use legs, leave all leg references empty.")]
  35. public Transform leftThigh; // 14 Optional
  36. [Tooltip("VRIK also supports legless characters.If you do not wish to use legs, leave all leg references empty.")]
  37. public Transform leftCalf; // 15 Optional
  38. [Tooltip("VRIK also supports legless characters.If you do not wish to use legs, leave all leg references empty.")]
  39. public Transform leftFoot; // 16 Optional
  40. [Tooltip("Optional")]
  41. public Transform leftToes; // 17 Optional
  42. [Tooltip("VRIK also supports legless characters.If you do not wish to use legs, leave all leg references empty.")]
  43. public Transform rightThigh; // 18 Optional
  44. [Tooltip("VRIK also supports legless characters.If you do not wish to use legs, leave all leg references empty.")]
  45. public Transform rightCalf; // 19 Optional
  46. [Tooltip("VRIK also supports legless characters.If you do not wish to use legs, leave all leg references empty.")]
  47. public Transform rightFoot; // 20 Optional
  48. [Tooltip("Optional")]
  49. public Transform rightToes; // 21 Optional
  50. /// <summary>
  51. /// Returns an array of all the Transforms in the definition.
  52. /// </summary>
  53. public Transform[] GetTransforms() {
  54. return new Transform[22] {
  55. root, pelvis, spine, chest, neck, head, leftShoulder, leftUpperArm, leftForearm, leftHand, rightShoulder, rightUpperArm, rightForearm, rightHand, leftThigh, leftCalf, leftFoot, leftToes, rightThigh, rightCalf, rightFoot, rightToes
  56. };
  57. }
  58. /// <summary>
  59. /// Returns true if all required Transforms have been assigned (shoulder, toe and neck bones are optional).
  60. /// </summary>
  61. public bool isFilled {
  62. get {
  63. if (
  64. root == null ||
  65. pelvis == null ||
  66. spine == null ||
  67. head == null ||
  68. leftUpperArm == null ||
  69. leftForearm == null ||
  70. leftHand == null ||
  71. rightUpperArm == null ||
  72. rightForearm == null ||
  73. rightHand == null
  74. ) return false;
  75. // If all leg bones are null, it is valid
  76. bool noLegBones =
  77. leftThigh == null &&
  78. leftCalf == null &&
  79. leftFoot == null &&
  80. rightThigh == null &&
  81. rightCalf == null &&
  82. rightFoot == null;
  83. if (noLegBones) return true;
  84. bool atLeastOneLegBoneMissing =
  85. leftThigh == null ||
  86. leftCalf == null ||
  87. leftFoot == null ||
  88. rightThigh == null ||
  89. rightCalf == null ||
  90. rightFoot == null;
  91. if (atLeastOneLegBoneMissing) return false;
  92. // Shoulder, toe and neck bones are optional
  93. return true;
  94. }
  95. }
  96. /// <summary>
  97. /// Returns true if none of the Transforms have been assigned.
  98. /// </summary>
  99. public bool isEmpty {
  100. get {
  101. if (
  102. root != null ||
  103. pelvis != null ||
  104. spine != null ||
  105. chest != null ||
  106. neck != null ||
  107. head != null ||
  108. leftShoulder != null ||
  109. leftUpperArm != null ||
  110. leftForearm != null ||
  111. leftHand != null ||
  112. rightShoulder != null ||
  113. rightUpperArm != null ||
  114. rightForearm != null ||
  115. rightHand != null ||
  116. leftThigh != null ||
  117. leftCalf != null ||
  118. leftFoot != null ||
  119. leftToes != null ||
  120. rightThigh != null ||
  121. rightCalf != null ||
  122. rightFoot != null ||
  123. rightToes != null
  124. ) return false;
  125. return true;
  126. }
  127. }
  128. /// <summary>
  129. /// Auto-detects VRIK references. Works with a Humanoid Animator on the root gameobject only.
  130. /// </summary>
  131. public static bool AutoDetectReferences(Transform root, out References references) {
  132. references = new References();
  133. var animator = root.GetComponentInChildren<Animator>();
  134. if (animator == null || !animator.isHuman) {
  135. Debug.LogWarning("VRIK needs a Humanoid Animator to auto-detect biped references. Please assign references manually.");
  136. return false;
  137. }
  138. references.root = root;
  139. references.pelvis = animator.GetBoneTransform(HumanBodyBones.Hips);
  140. references.spine = animator.GetBoneTransform(HumanBodyBones.Spine);
  141. references.chest = animator.GetBoneTransform(HumanBodyBones.Chest);
  142. references.neck = animator.GetBoneTransform(HumanBodyBones.Neck);
  143. references.head = animator.GetBoneTransform(HumanBodyBones.Head);
  144. references.leftShoulder = animator.GetBoneTransform(HumanBodyBones.LeftShoulder);
  145. references.leftUpperArm = animator.GetBoneTransform(HumanBodyBones.LeftUpperArm);
  146. references.leftForearm = animator.GetBoneTransform(HumanBodyBones.LeftLowerArm);
  147. references.leftHand = animator.GetBoneTransform(HumanBodyBones.LeftHand);
  148. references.rightShoulder = animator.GetBoneTransform(HumanBodyBones.RightShoulder);
  149. references.rightUpperArm = animator.GetBoneTransform(HumanBodyBones.RightUpperArm);
  150. references.rightForearm = animator.GetBoneTransform(HumanBodyBones.RightLowerArm);
  151. references.rightHand = animator.GetBoneTransform(HumanBodyBones.RightHand);
  152. references.leftThigh = animator.GetBoneTransform(HumanBodyBones.LeftUpperLeg);
  153. references.leftCalf = animator.GetBoneTransform(HumanBodyBones.LeftLowerLeg);
  154. references.leftFoot = animator.GetBoneTransform(HumanBodyBones.LeftFoot);
  155. references.leftToes = animator.GetBoneTransform(HumanBodyBones.LeftToes);
  156. references.rightThigh = animator.GetBoneTransform(HumanBodyBones.RightUpperLeg);
  157. references.rightCalf = animator.GetBoneTransform(HumanBodyBones.RightLowerLeg);
  158. references.rightFoot = animator.GetBoneTransform(HumanBodyBones.RightFoot);
  159. references.rightToes = animator.GetBoneTransform(HumanBodyBones.RightToes);
  160. return true;
  161. }
  162. }
  163. // Open the User Manual URL
  164. [ContextMenu("User Manual")]
  165. protected override void OpenUserManual() {
  166. Application.OpenURL("http://www.root-motion.com/finalikdox/html/page16.html");
  167. }
  168. // Open the Script Reference URL
  169. [ContextMenu("Scrpt Reference")]
  170. protected override void OpenScriptReference() {
  171. Application.OpenURL("http://www.root-motion.com/finalikdox/html/class_root_motion_1_1_final_i_k_1_1_v_r_i_k.html");
  172. }
  173. // Open a video tutorial about setting up the component
  174. [ContextMenu("TUTORIAL VIDEO (STEAMVR SETUP)")]
  175. void OpenSetupTutorial() {
  176. Application.OpenURL("https://www.youtube.com/watch?v=6Pfx7lYQiIA&feature=youtu.be");
  177. }
  178. /// <summary>
  179. /// Bone mapping. Right-click on the component header and select 'Auto-detect References' of fill in manually if not a Humanoid character. Chest, neck, shoulder and toe bones are optional. VRIK also supports legless characters. If you do not wish to use legs, leave all leg references empty.
  180. /// </summary>
  181. [ContextMenuItem("Auto-detect References", "AutoDetectReferences")]
  182. [Tooltip("Bone mapping. Right-click on the component header and select 'Auto-detect References' of fill in manually if not a Humanoid character. Chest, neck, shoulder and toe bones are optional. VRIK also supports legless characters. If you do not wish to use legs, leave all leg references empty.")]
  183. public References references = new References();
  184. /// <summary>
  185. /// The solver.
  186. /// </summary>
  187. [Tooltip("The VRIK solver.")]
  188. public IKSolverVR solver = new IKSolverVR();
  189. /// <summary>
  190. /// Auto-detects bone references for this VRIK. Works with a Humanoid Animator on the gameobject only.
  191. /// </summary>
  192. [ContextMenu("Auto-detect References")]
  193. public void AutoDetectReferences() {
  194. References.AutoDetectReferences(transform, out references);
  195. }
  196. /// <summary>
  197. /// Fills in arm wristToPalmAxis and palmToThumbAxis.
  198. /// </summary>
  199. [ContextMenu("Guess Hand Orientations")]
  200. public void GuessHandOrientations() {
  201. solver.GuessHandOrientations(references, false);
  202. }
  203. public override IKSolver GetIKSolver() {
  204. return solver as IKSolver;
  205. }
  206. protected override void InitiateSolver() {
  207. if (references.isEmpty) AutoDetectReferences();
  208. if (references.isFilled) solver.SetToReferences(references);
  209. base.InitiateSolver();
  210. }
  211. protected override void UpdateSolver() {
  212. if (references.root != null && references.root.localScale == Vector3.zero) {
  213. Debug.LogError("VRIK Root Transform's scale is zero, can not update VRIK. Make sure you have not calibrated the character to a zero scale.", transform);
  214. enabled = false;
  215. return;
  216. }
  217. base.UpdateSolver();
  218. }
  219. }
  220. }