FBIKHandsOnProp.cs 2.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  1. using UnityEngine;
  2. using System.Collections;
  3. using RootMotion.FinalIK;
  4. namespace RootMotion.Demos {
  5. /// <summary>
  6. /// Maintains FBBIK hands on a 2-handed prop, regardless of position offset of the hand effectors
  7. /// </summary>
  8. public class FBIKHandsOnProp: MonoBehaviour {
  9. public FullBodyBipedIK ik; // Reference to the FBBIK component
  10. public bool leftHanded;
  11. void Awake() {
  12. // Add to OnPreUpdate delegate to get a call before the solver starts updating
  13. ik.solver.OnPreRead += OnPreRead;
  14. }
  15. private void OnPreRead() {
  16. if (leftHanded) HandsOnProp(ik.solver.leftHandEffector, ik.solver.rightHandEffector);
  17. else HandsOnProp(ik.solver.rightHandEffector, ik.solver.leftHandEffector);
  18. }
  19. private void HandsOnProp(IKEffector mainHand, IKEffector otherHand) {
  20. // Get the animated direction from the main hand to the other hand
  21. Vector3 toOtherHand = otherHand.bone.position - mainHand.bone.position;
  22. // Get the hand direction relative to the main hand's rotation
  23. Vector3 otherHandRelativeDirection = Quaternion.Inverse(mainHand.bone.rotation) * toOtherHand;
  24. // Get the center point of two hands
  25. Vector3 handsCenter = mainHand.bone.position + (toOtherHand * 0.5f);
  26. // Get the other hand's rotation relative to the main hand's rotation
  27. Quaternion otherHandRelativeRotation = Quaternion.Inverse(mainHand.bone.rotation) * otherHand.bone.rotation;
  28. // Get the direction from the main hand to the other hand that icludes effector position offsets
  29. Vector3 toOtherHandWithOffset = (otherHand.bone.position + otherHand.positionOffset) - (mainHand.bone.position + mainHand.positionOffset);
  30. // Get the center point of two hands that includes effector position offsets
  31. Vector3 handsCenterWithOffset = (mainHand.bone.position + mainHand.positionOffset) + (toOtherHand * 0.5f);
  32. // Main hand position
  33. mainHand.position = (mainHand.bone.position + mainHand.positionOffset) + (handsCenterWithOffset - handsCenter);
  34. mainHand.positionWeight = 1f;
  35. // Main hand rotation
  36. Quaternion rotationOffset = Quaternion.FromToRotation(toOtherHand, toOtherHandWithOffset);
  37. mainHand.bone.rotation = rotationOffset * mainHand.bone.rotation;
  38. // Other hand position
  39. otherHand.position = mainHand.position + mainHand.bone.rotation * otherHandRelativeDirection;
  40. otherHand.positionWeight = 1f;
  41. // Other hand rotation
  42. otherHand.bone.rotation = mainHand.bone.rotation * otherHandRelativeRotation;
  43. ik.solver.leftArmMapping.maintainRotationWeight = 1f;
  44. ik.solver.rightArmMapping.maintainRotationWeight = 1f;
  45. }
  46. // Clean up delegates
  47. void OnDestroy() {
  48. if (ik != null) {
  49. ik.solver.OnPreRead -= OnPreRead;
  50. }
  51. }
  52. }
  53. }