using UnityEngine; using System.Collections; using RootMotion.FinalIK; namespace RootMotion.Demos { /// /// Making a character hold on to a target and swing about it while maintaining his animation. /// [RequireComponent(typeof(FullBodyBipedIK))] public class PendulumExample : MonoBehaviour { [Tooltip("The master weight of this script.")] [Range(0f, 1f)] public float weight = 1f; [Tooltip("Multiplier for the distance of the root to the target.")] public float hangingDistanceMlp = 1.3f; [Tooltip("Where does the root of the character land when weight is blended out?")] [HideInInspector] public Vector3 rootTargetPosition; [Tooltip("How is the root of the character rotated when weight is blended out?")] [HideInInspector] public Quaternion rootTargetRotation; public Transform target; public Transform leftHandTarget; public Transform rightHandTarget; public Transform leftFootTarget; public Transform rightFootTarget; public Transform pelvisTarget; public Transform bodyTarget; public Transform headTarget; public Vector3 pelvisDownAxis = Vector3.right; private FullBodyBipedIK ik; private Quaternion rootRelativeToPelvis; private Vector3 pelvisToRoot; private float lastWeight; void Start() { ik = GetComponent(); // Connect the left hand to the target Quaternion targetRotation = target.rotation; target.rotation = leftHandTarget.rotation; FixedJoint j = target.gameObject.AddComponent(); j.connectedBody = leftHandTarget.GetComponent(); target.GetComponent().MoveRotation(targetRotation); //target.rotation = targetRotation; // Remember the rotation of the root relative to the pelvis rootRelativeToPelvis = Quaternion.Inverse(pelvisTarget.rotation) * transform.rotation; // Remember the position of the root relative to the pelvis pelvisToRoot = Quaternion.Inverse(ik.references.pelvis.rotation) * (transform.position - ik.references.pelvis.position); rootTargetPosition = transform.position; rootTargetRotation = transform.rotation; lastWeight = weight; } void LateUpdate() { // Set effector weights if (weight > 0f) { ik.solver.leftHandEffector.positionWeight = weight; ik.solver.leftHandEffector.rotationWeight = weight; } else { rootTargetPosition = transform.position; rootTargetRotation = transform.rotation; if (lastWeight > 0f) { ik.solver.leftHandEffector.positionWeight = 0f; ik.solver.leftHandEffector.rotationWeight = 0f; } } lastWeight = weight; if (weight <= 0f) return; // Position the character relative to the ragdoll pelvis transform.position = Vector3.Lerp(rootTargetPosition, pelvisTarget.position + pelvisTarget.rotation * pelvisToRoot * hangingDistanceMlp, weight); // Rotate the character to the ragdoll pelvis transform.rotation = Quaternion.Lerp(rootTargetRotation, pelvisTarget.rotation * rootRelativeToPelvis, weight); // Set ik effector positions ik.solver.leftHandEffector.position = leftHandTarget.position; ik.solver.leftHandEffector.rotation = leftHandTarget.rotation; // Get the normal hanging direction Vector3 dir = ik.references.pelvis.rotation * pelvisDownAxis; // Rotating the limbs // Get the rotation from normal hangind direction to the right arm ragdoll direction Quaternion rightArmRot = Quaternion.FromToRotation(dir, rightHandTarget.position - headTarget.position); // Rotate the right arm by that offset ik.references.rightUpperArm.rotation = Quaternion.Lerp(Quaternion.identity, rightArmRot, weight) * ik.references.rightUpperArm.rotation; Quaternion leftLegRot = Quaternion.FromToRotation(dir, leftFootTarget.position - bodyTarget.position); ik.references.leftThigh.rotation = Quaternion.Lerp(Quaternion.identity, leftLegRot, weight) * ik.references.leftThigh.rotation; Quaternion rightLegRot = Quaternion.FromToRotation(dir, rightFootTarget.position - bodyTarget.position); ik.references.rightThigh.rotation = Quaternion.Lerp(Quaternion.identity, rightLegRot, weight) * ik.references.rightThigh.rotation; } } }