PendulumExample.cs 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. using UnityEngine;
  2. using System.Collections;
  3. using RootMotion.FinalIK;
  4. namespace RootMotion.Demos {
  5. /// <summary>
  6. /// Making a character hold on to a target and swing about it while maintaining his animation.
  7. /// </summary>
  8. public class PendulumExample : MonoBehaviour {
  9. [Tooltip("The master weight of this script.")]
  10. [Range(0f, 1f)] public float weight = 1f;
  11. [Tooltip("Multiplier for the distance of the root to the target.")]
  12. public float hangingDistanceMlp = 1.3f;
  13. [Tooltip("Where does the root of the character land when weight is blended out?")]
  14. [HideInInspector] public Vector3 rootTargetPosition;
  15. [Tooltip("How is the root of the character rotated when weight is blended out?")]
  16. [HideInInspector] public Quaternion rootTargetRotation;
  17. public Transform target;
  18. public Transform leftHandTarget;
  19. public Transform rightHandTarget;
  20. public Transform leftFootTarget;
  21. public Transform rightFootTarget;
  22. public Transform pelvisTarget;
  23. public Transform bodyTarget;
  24. public Transform headTarget;
  25. public Vector3 pelvisDownAxis = Vector3.right;
  26. private FullBodyBipedIK ik;
  27. private Quaternion rootRelativeToPelvis;
  28. private Vector3 pelvisToRoot;
  29. private float lastWeight;
  30. void Start() {
  31. ik = GetComponent<FullBodyBipedIK>();
  32. // Connect the left hand to the target
  33. Quaternion targetRotation = target.rotation;
  34. target.rotation = leftHandTarget.rotation;
  35. FixedJoint j = target.gameObject.AddComponent<FixedJoint>();
  36. j.connectedBody = leftHandTarget.GetComponent<Rigidbody>();
  37. target.GetComponent<Rigidbody>().MoveRotation(targetRotation);
  38. //target.rotation = targetRotation;
  39. // Remember the rotation of the root relative to the pelvis
  40. rootRelativeToPelvis = Quaternion.Inverse(pelvisTarget.rotation) * transform.rotation;
  41. // Remember the position of the root relative to the pelvis
  42. pelvisToRoot = Quaternion.Inverse(ik.references.pelvis.rotation) * (transform.position - ik.references.pelvis.position);
  43. rootTargetPosition = transform.position;
  44. rootTargetRotation = transform.rotation;
  45. lastWeight = weight;
  46. }
  47. void LateUpdate() {
  48. // Set effector weights
  49. if (weight > 0f) {
  50. ik.solver.leftHandEffector.positionWeight = weight;
  51. ik.solver.leftHandEffector.rotationWeight = weight;
  52. } else {
  53. rootTargetPosition = transform.position;
  54. rootTargetRotation = transform.rotation;
  55. if (lastWeight > 0f) {
  56. ik.solver.leftHandEffector.positionWeight = 0f;
  57. ik.solver.leftHandEffector.rotationWeight = 0f;
  58. }
  59. }
  60. lastWeight = weight;
  61. if (weight <= 0f) return;
  62. // Position the character relative to the ragdoll pelvis
  63. transform.position = Vector3.Lerp(rootTargetPosition, pelvisTarget.position + pelvisTarget.rotation * pelvisToRoot * hangingDistanceMlp, weight);
  64. // Rotate the character to the ragdoll pelvis
  65. transform.rotation = Quaternion.Lerp(rootTargetRotation, pelvisTarget.rotation * rootRelativeToPelvis, weight);
  66. // Set ik effector positions
  67. ik.solver.leftHandEffector.position = leftHandTarget.position;
  68. ik.solver.leftHandEffector.rotation = leftHandTarget.rotation;
  69. // Get the normal hanging direction
  70. Vector3 dir = ik.references.pelvis.rotation * pelvisDownAxis;
  71. // Rotating the limbs
  72. // Get the rotation from normal hangind direction to the right arm ragdoll direction
  73. Quaternion rightArmRot = Quaternion.FromToRotation(dir, rightHandTarget.position - headTarget.position);
  74. // Rotate the right arm by that offset
  75. ik.references.rightUpperArm.rotation = Quaternion.Lerp(Quaternion.identity, rightArmRot, weight) * ik.references.rightUpperArm.rotation;
  76. Quaternion leftLegRot = Quaternion.FromToRotation(dir, leftFootTarget.position - bodyTarget.position);
  77. ik.references.leftThigh.rotation = Quaternion.Lerp(Quaternion.identity, leftLegRot, weight) * ik.references.leftThigh.rotation;
  78. Quaternion rightLegRot = Quaternion.FromToRotation(dir, rightFootTarget.position - bodyTarget.position);
  79. ik.references.rightThigh.rotation = Quaternion.Lerp(Quaternion.identity, rightLegRot, weight) * ik.references.rightThigh.rotation;
  80. }
  81. }
  82. }