Однако, часто бывает полезно взглянуть на задачу с другой стороны. Можно работать в обратном направлении и задавать позиции родительских костей в зависимости от положения дочерних. Это очень удобно, когда вы хотите, чтобы персонаж касался выбранных игроком объектов или реалистично ходил по неровной поверхности. Этот метод называется Инверсная Кинематика (IK) и доступен в Mecanim для любого человекоподобного персонажа с правильно настроенным скелетом.
Чтобы использовать IK вам нужно разместить на сцене объекты, с которыми ваш персонаж будет взаимодействовать, а затем настроить IK через скрипт, использующий специальные функции для IK-анимации: SetIKPositionWeight, SetIKRotationWeight, SetIKPosition, SetIKRotation, SetLookAtPosition, bodyPosition, bodyRotation.
На картинке выше видно, что персонаж держит в руках цилиндр. Как это сделать?
Нужно разместить на сцене персонажа с настроенным скелетом и добавить к нему скрипт, который будет управлять IK. Назовем его IKCtrl.
Синтаксис:
Используется csharp
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>();
}
//Возвращаемся к IK
void OnAnimatorIK()
{
if(animator) {
//Если IK включен, то направляем правую руку к цели
if(ikActive) {
//weight = 1.0 означает, что правая рука будет стремиться к цели с максимальным приоритетом.
animator.SetIKPositionWeight(AvatarIKGoal.RightHand,1.0f);
animator.SetIKRotationWeight(AvatarIKGoal.RightHand,1.0f);
//Направляем правую руку к цели.
if(rightHandObj != null) {
animator.SetIKPosition(AvatarIKGoal.RightHand,rightHandObj.position);
animator.SetIKRotation(AvatarIKGoal.RightHand,rightHandObj.rotation);
}
}
//Если IK не активен, тогда стремиться к оригинальной позиции.
else {
animator.SetIKPositionWeight(AvatarIKGoal.RightHand,0);
animator.SetIKRotationWeight(AvatarIKGoal.RightHand,0);
}
}
}
}
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>();
}
//Возвращаемся к IK
void OnAnimatorIK()
{
if(animator) {
//Если IK включен, то направляем правую руку к цели
if(ikActive) {
//weight = 1.0 означает, что правая рука будет стремиться к цели с максимальным приоритетом.
animator.SetIKPositionWeight(AvatarIKGoal.RightHand,1.0f);
animator.SetIKRotationWeight(AvatarIKGoal.RightHand,1.0f);
//Направляем правую руку к цели.
if(rightHandObj != null) {
animator.SetIKPosition(AvatarIKGoal.RightHand,rightHandObj.position);
animator.SetIKRotation(AvatarIKGoal.RightHand,rightHandObj.rotation);
}
}
//Если IK не активен, тогда стремиться к оригинальной позиции.
else {
animator.SetIKPositionWeight(AvatarIKGoal.RightHand,0);
animator.SetIKRotationWeight(AvatarIKGoal.RightHand,0);
}
}
}
}
Создайте цилиндр и разместите его на сцене так, как вам нужно. Далее переместите его из инспектора в "Right Hand Obj" скрипта IKCtrl.
Запустите игру и посмотрите, как персонаж берет и отпускает цилиндр при включении и выключении ikActive.
http://docs.unity3d.com/Documentation/Manual/InverseKinematics.html - оригинал.