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();
}
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, 1.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
调整:Ik Active 复选框,开启或关闭IK效果 以下GIF,实现刚开始是没有开启IK的,然后开启IK后,可以控制一部分IK部位信息(目标位置、旋转)
目前脚本中只是使用了SetIKPosition(测试foot(脚), hand(手))的测试 还有SetIKHintPosition可以测试knee(膝盖),elbow(手肘)的部位IK,这儿就不测试了,只是部位不同
ReferencesUnity Animator动画状态机 深入理解(二)IK控制