Files
2026-03-04 10:03:45 +08:00

99 lines
3.4 KiB
C#

using RootMotion.FinalIK;
using UnityEngine;
namespace RootMotion.Demos
{
[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;
private void Start()
{
ik = GetComponent<FullBodyBipedIK>();
Quaternion rotation = target.rotation;
target.rotation = leftHandTarget.rotation;
target.gameObject.AddComponent<FixedJoint>().connectedBody = leftHandTarget.GetComponent<Rigidbody>();
target.GetComponent<Rigidbody>().MoveRotation(rotation);
rootRelativeToPelvis = Quaternion.Inverse(pelvisTarget.rotation) * base.transform.rotation;
pelvisToRoot = Quaternion.Inverse(ik.references.pelvis.rotation) * (base.transform.position - ik.references.pelvis.position);
rootTargetPosition = base.transform.position;
rootTargetRotation = base.transform.rotation;
lastWeight = weight;
}
private void LateUpdate()
{
if (weight > 0f)
{
ik.solver.leftHandEffector.positionWeight = weight;
ik.solver.leftHandEffector.rotationWeight = weight;
}
else
{
rootTargetPosition = base.transform.position;
rootTargetRotation = base.transform.rotation;
if (lastWeight > 0f)
{
ik.solver.leftHandEffector.positionWeight = 0f;
ik.solver.leftHandEffector.rotationWeight = 0f;
}
}
lastWeight = weight;
if (!(weight <= 0f))
{
base.transform.position = Vector3.Lerp(rootTargetPosition, pelvisTarget.position + pelvisTarget.rotation * pelvisToRoot * hangingDistanceMlp, weight);
base.transform.rotation = Quaternion.Lerp(rootTargetRotation, pelvisTarget.rotation * rootRelativeToPelvis, weight);
ik.solver.leftHandEffector.position = leftHandTarget.position;
ik.solver.leftHandEffector.rotation = leftHandTarget.rotation;
Vector3 fromDirection = ik.references.pelvis.rotation * pelvisDownAxis;
Quaternion b = Quaternion.FromToRotation(fromDirection, rightHandTarget.position - headTarget.position);
ik.references.rightUpperArm.rotation = Quaternion.Lerp(Quaternion.identity, b, weight) * ik.references.rightUpperArm.rotation;
Quaternion b2 = Quaternion.FromToRotation(fromDirection, leftFootTarget.position - bodyTarget.position);
ik.references.leftThigh.rotation = Quaternion.Lerp(Quaternion.identity, b2, weight) * ik.references.leftThigh.rotation;
Quaternion b3 = Quaternion.FromToRotation(fromDirection, rightFootTarget.position - bodyTarget.position);
ik.references.rightThigh.rotation = Quaternion.Lerp(Quaternion.identity, b3, weight) * ik.references.rightThigh.rotation;
}
}
}
}