Unity - IK test

Code

using UnityEngine;

public class MyIK : MonoBehaviour
{
    public Transform headObj = null;
    public Transform bodyObj = null;
    public Transform leftFootObj = null;
    public Transform rightFootObj = null;
    public Transform leftHandObj = null;
    public Transform rightHandObj = null;
    public Transform lookAtObj = null;

    public bool ikActive = false;

    private Animator animator;

    void Start()
    {
        animator = GetComponent<Animator>();
    }

    void OnAnimatorIK(int layerIndex)
    {
        if (headObj == null
            || bodyObj == null
            || leftFootObj == null 
            || rightFootObj == null 
            || leftHandObj == null 
            || rightHandObj == null 
            || lookAtObj == null)
            return;

        if (animator == null) return;

        if (ikActive)
        {
            animator.SetIKPositionWeight(AvatarIKGoal.LeftFoot, 0.0f);
            animator.SetIKRotationWeight(AvatarIKGoal.LeftFoot, 1.0f);
            animator.SetIKPositionWeight(AvatarIKGoal.LeftHand, 1.0f);
            animator.SetIKRotationWeight(AvatarIKGoal.LeftHand, 1.0f);
            animator.SetIKPositionWeight(AvatarIKGoal.RightFoot, 1.0f);
            animator.SetIKRotationWeight(AvatarIKGoal.RightFoot, 1.0f);
            animator.SetIKPositionWeight(AvatarIKGoal.RightHand, 1.0f);
            animator.SetIKRotationWeight(AvatarIKGoal.RightHand, 1.0f);
            animator.SetLookAtWeight(1.0f, 0.3f, 1.0f, 0.5f);

            if (bodyObj != null)
            {
                animator.bodyPosition = bodyObj.position;
                animator.bodyRotation = bodyObj.rotation;
            }

            if (leftHandObj != null)
            {
                animator.SetIKPosition(AvatarIKGoal.LeftHand, leftHandObj.position);
                animator.SetIKRotation(AvatarIKGoal.LeftHand, leftHandObj.rotation);
            }
            if (rightFootObj != null)
            {
                animator.SetIKPosition(AvatarIKGoal.RightFoot, rightFootObj.position);
                animator.SetIKRotation(AvatarIKGoal.RightFoot, rightFootObj.rotation);
            }
            if (leftFootObj != null)
            {
                animator.SetIKPosition(AvatarIKGoal.LeftFoot, leftFootObj.position);
                animator.SetIKRotation(AvatarIKGoal.LeftFoot, leftFootObj.rotation);
            }
            if (rightHandObj != null)
            {
                animator.SetIKPosition(AvatarIKGoal.RightHand, rightHandObj.position);
                animator.SetIKRotation(AvatarIKGoal.RightHand, rightHandObj.rotation);
            }

            if (lookAtObj != null)
            {
                animator.SetLookAtPosition(lookAtObj.position);
            }
        }
        else
        {
            if (bodyObj != null)
            {
                bodyObj.position = animator.bodyPosition;
                bodyObj.rotation = animator.bodyRotation;
            }

            if (leftFootObj != null)
            {
                leftFootObj.position = animator.GetBoneTransform(HumanBodyBones.LeftFoot).transform.position; // animator.GetIKPosition(AvatarIKGoal.LeftFoot);
                leftFootObj.rotation = animator.GetBoneTransform(HumanBodyBones.LeftFoot).transform.rotation; // animator.GetIKRotation(AvatarIKGoal.LeftFoot);
            }

            if (rightFootObj != null)
            {
                rightFootObj.position = animator.GetBoneTransform(HumanBodyBones.RightFoot).transform.position; // animator.GetIKPosition(AvatarIKGoal.RightFoot);
                rightFootObj.rotation = animator.GetBoneTransform(HumanBodyBones.RightFoot).transform.rotation; // animator.GetIKRotation(AvatarIKGoal.RightFoot);
            }

            if (leftHandObj != null)
            {
                leftHandObj.position = animator.GetBoneTransform(HumanBodyBones.LeftHand).transform.position; // animator.GetIKPosition(AvatarIKGoal.LeftHand);
                leftHandObj.rotation = animator.GetBoneTransform(HumanBodyBones.LeftHand).transform.rotation; //  animator.GetIKRotation(AvatarIKGoal.LeftHand);
            }

            if (rightHandObj != null)
            {
                rightHandObj.position = animator.GetBoneTransform(HumanBodyBones.RightHand).transform.position; // animator.GetIKPosition(AvatarIKGoal.RightHand);
                rightHandObj.rotation = animator.GetBoneTransform(HumanBodyBones.RightHand).transform.rotation; // animator.GetIKRotation(AvatarIKGoal.RightHand);
            }

            if (lookAtObj != null)
            {
                lookAtObj.position = headObj.position + headObj.forward;
            }
            animator.SetIKPositionWeight(AvatarIKGoal.LeftFoot, 0);
            animator.SetIKRotationWeight(AvatarIKGoal.LeftFoot, 0);
            animator.SetIKPositionWeight(AvatarIKGoal.LeftHand, 0);
            animator.SetIKRotationWeight(AvatarIKGoal.LeftHand, 0);
            animator.SetIKPositionWeight(AvatarIKGoal.RightFoot, 0);
            animator.SetIKRotationWeight(AvatarIKGoal.RightFoot, 0);
            animator.SetIKPositionWeight(AvatarIKGoal.RightHand, 0);
            animator.SetIKRotationWeight(AvatarIKGoal.RightHand, 0);
            animator.SetLookAtWeight(0.0f);
        }
    }
}

Runtime

Adjust: Ik Active check box to turn IK effects on or off

In the following GIF, the implementation does not turn on IK at first, and then after turning on IK, you can control part of IK part information (target position, rotation)

At present, only the test of SetIKPosition (test foot, hand) is used in the script
And SetIKHintPosition can test the IK of knee and elbow. It's not tested here, but the parts are different

References

Deep understanding of Unity Animator animation state machine (2) IK control

Tags: Unity

Posted on Tue, 05 Nov 2019 08:59:34 -0800 by phpdev12