反向动力学 (Inverse Kinematics)(仅限专业版 (Pro))

大多数动画通过旋转调整骨架中关节的角度为预定值来制作。子关节的位置根据其父关节的旋转而改变,因此,关节链的端点由其所包含的单个关节的角度和相对位置决定。这种构成骨架的方法称为正向动力学

因此,从相反的角度查看构成关节的任务通常十分有用 – 在空间中给出一个选择的位置,逆向操作,找到一种定向关节的有效方式,这样端点就落在该位置。想要角色在用户选择的某一点触摸一个物体或者将角色双脚稳稳地固定在不平坦的表面上时,这种方式非常有效。这种方式称为反向动力学 (Inverse Kinematics) (IK),支持 Mecanim,可用于任何含有正确配置的 Avatar 的类人角色。

要为角色设置IK,通常需要拥有与角色互动的场景四周的物体,然后通过脚本设置 IK,特别是通过此类动画器 (Animator) 功能: SetIKPositionWeightSetIKRotationWeightSetIKPositionSetIKRotationSetLookAtPositionbodyPositionbodyRotation

在上图中,我们展示了一个角色正抓住一个圆柱形物体。我们如何才能做到这一点?

我们先从一个拥有有效 Avatar 的角色入手,然后向该角色附加一个实际上处理 IK 的脚本(我们就称它为 IKCtrl):

using UnityEngine;
using System;
using System.Collections;

[RequireComponent(typeof(Animator))]  

public class IKCtrl :MonoBehaviour {

	protected Animator animator;

	public bool ikActive = false;
	public Transform rightHandObj = null;

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

//a callback for calculating IK
	void OnAnimatorIK()
	{
	      if(animator) {

//if the IK is active, set the position and rotation directly to the goal. 
			if(ikActive) {

//weight = 1.0 for the right hand means position and rotation will be at the IK goal (the place the character wants to grab)
				animator.SetIKPositionWeight(AvatarIKGoal.RightHand,1.0f);
				animator.SetIKRotationWeight(AvatarIKGoal.RightHand,1.0f);

			        //set the position and the rotation of the right hand where the external object is
				if(rightHandObj != null) {
					animator.SetIKPosition(AvatarIKGoal.RightHand,rightHandObj.position);
					animator.SetIKRotation(AvatarIKGoal.RightHand,rightHandObj.rotation);
				}					

			}

//if the IK is not active, set the position and rotation of the hand back to the original position
			else {			
				animator.SetIKPositionWeight(AvatarIKGoal.RightHand,0);
				animator.SetIKRotationWeight(AvatarIKGoal.RightHand,0);				
			}
		}
	}	  
}

由于我们不打算让角色用手抓住整个物体,我们在圆柱体上放置了一个手抓的球体,并相应转动该球体。

该球体然后被列为 IKCtrl 脚本的“右手对象 (Right Hand Obj)” 属性

点击 IKActive 复选框,观察角色抓取、松开物体的过程

(返回 Mecanim 简介

Page last updated: 2013-06-24