什么是反向动力学
一般我们都是通过父节点来调动子节点运动,而在实际开发过程中,有时候我们需要子节点带动父节点进行相应的动作。这种情况就是反向动力学。其实在国内的游戏中很少看见IK动画,一般而言国外的游戏较多。 通俗讲:就是使用场景中的各种物体来控制和影响角色身体部位的运动
作用
- 让我们的人物模型的胳膊一直指向某一个物体(在不需要动画的前提下)
- 设置人物头部一直看向某个位置
- 人物走路踩到了石头,就需要由脚的子节点带动全身骨骼做出踩到石头的响应
- 例如刺客信条,手部带动身体的爬行
- 比如跳跃到某个位置
为什么能实现呢?
首先我们要知道人的模型是由以节点模型为基础搭建而成的,通过反向动力学,我们可以调动节点来实现人物模型的运动,比如让手臂指向某一个物体a — 我们调用反向动力学,使得手臂的手掌节点指向物体a,然后手掌节点调动关节节点再调用肩膀处的节点,实现整个手臂指向物体a
前提
对一个游戏物体使用反向动力学(IK)的前提是这个游戏物体具有动画器控制器
API:
API | 介绍 |
---|---|
OnAnimatorIK(int layeIndex) | 设置动画IK的回调layeIndex:调用反向动力学解锁器的层的索引;对应Layer的序号,每个勾选了IKPass的layer调用一次 |
AvatarIKGoal | 反向动力学目标[枚举类型];LeftFoot左脚/RightFoot右脚/LeftHand左手/RightHand右手 |
SetIKPositionWeight(AvatarIKGoal goal,float value) | 设置反向动力学目标的转换权重 |
SetIKPosition(AvatarIKGoal goal,Vector3 goalPosition) | 设置反向动力学目标的位置 |
SetLookAtPosition(Vector3 lookAtPosition) | 设置看向的位置 |
public Vector3 bodyPosition; | 身体质心的位置 |
public Quaternion bodyRotation; | 身体质心的旋转(只应在OnAnimatorIK()函数调用中设置该值) |
简单的使用
游戏人物盯着某个游戏对象看,来达到时刻注视的效果。
创建一个位置变量来承接后面我们获取的要指向或看向的游戏物体的坐标
//目标物体位置
public Transform target;
脚本绑定要看的物体
打开IK开关
游戏人物盯着某个游戏对象看,来达到时刻注视的效果
public class ManScript : MonoBehaviour
{
//目标物体位置
public Transform target;
private Animator animator;
void Start()
{
animator = GetComponent<Animator>();
}
void Update() {
}
// 特定方法 layerIndex:我们控制第几层的IK
void OnAnimatorIK(int layerIndex)
{
//设置头部IK权重
animator.SetLookAtWeight(1);
//设置头部看向的位置
animator.SetLookAtPosition(target.position);
}
}
效果
更复杂一点,就是让身体右手也跟着注释的对象移动或摆动
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ManScript : MonoBehaviour
{
//目标物体位置
public Transform target;
private Animator animator;
void Start()
{
animator = GetComponent<Animator>();
}
void Update()
{
}
// 特定方法 layerIndex:我们控制第几层的IK
void OnAnimatorIK(int layerIndex)
{
//设置头部IK权重
animator.SetLookAtWeight(1);
//设置头部看向的位置 后面还有
animator.SetLookAtPosition(target.position);
//设置右手IK
animator.SetIKPositionWeight(AvatarIKGoal.RightHand, 1);
//设置右手旋转权重
animator.SetIKRotationWeight(AvatarIKGoal.RightHand, 1);
//设置右手指向物体
animator.SetIKPosition(AvatarIKGoal.RightHand, target.position);
animator.SetIKRotation(AvatarIKGoal.RightHand, target.rotation);
}
}
效果
控制角色跳跃到某个位置
新增跳跃动画
代码控制人物跳跃到1,1,1点
public class ManScript : MonoBehaviour
{
//目标物体位置
public Transform target;
private Animator animator;
void Start()
{
animator = GetComponent<Animator>();
}
void Update()
{
//播放起跳动画
if (Input.GetKeyDown(KeyCode.Space))
{
animator.SetBool("Jump", true);
}
if (animator.IsInTransition(0)) return;//非过渡状态才开始匹配
//获取第一图层动画
AnimatorStateInfo info = animator.GetCurrentAnimatorStateInfo(0);
//判断动画是否是跳跃动画
if (info.IsName("Jump01"))
{
animator.SetBool("Jump", false);
//跳跃
// 第一个参数动作位置,第二个参数角色旋转,第三个是做动作的某个身体部位,第四个是权重信息,第五六参数是获取动画曲线
animator.MatchTarget(new Vector3(1, 1, 1), Quaternion.identity, AvatarTarget.LeftFoot, new MatchTargetWeightMask(Vector3.one, 0), 0.25f, 0.57f);
}
}
}
动画曲线参数可以从动画中取得,当人物开始起跳的时间,和跳跃完成的时间,这里根据不同的动画进行微调。
效果