效果(左侧模型动画,右侧模型IK控制)
模型动画下载及导入
推荐模型动画下载链接地址
https://actorcore.reallusion.com/
Unity导入教程参见以下链接地址(需要科学上网)
https://actorcore.reallusion.com/learn-and-support/my-software/unity/getting-started
导入完成后模型相关查看
配置模型动画控制器
拖拽模型预设到视图中
配置动画控制器(可自定义动画控制器)
创建新的控制器状态
,向Motion
属性中添加模型中的动画
- 通过修改
Status
属性来改变播放的动画
监听动画状态的脚本
using UnityEngine;
public class DanceAnimStateMachine : StateMachineBehaviour
{
// 进入当前状态时
override public void OnStateEnter(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
{
Debug.Log($"进入当前状态时");
}
// 当前状态更新时,每帧都会被调用
override public void OnStateUpdate(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
{
Debug.Log($"当前状态更新时,每帧都会被调用");
}
// 离开当前状态时
override public void OnStateExit(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
{
Debug.Log($"离开当前状态时");
}
// 在Animator.OnAnimatorMove()之后调用,这里可以处理动画根节点的位移
override public void OnStateMove(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
{
Debug.Log($"在Animator.OnAnimatorMove()之后调用,这里可以处理动画根节点的位移");
}
// 在Animator.OnAnimatorIK()之后调用,这里可以处理IK(反向运动学)动画
override public void OnStateIK(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
{
Debug.Log($"在Animator.OnAnimatorIK()之后调用,这里可以处理IK(反向运动学)动画");
}
}
脚本控制模型骨骼IK动画
创建自己的动画控制器
添加 T-Pose 动画到控制器
启用 IK Pass
模型骨骼IK控制脚本
using UnityEngine;
namespace Example_01.Scripts
{
public class ModelAnimByIK : MonoBehaviour
{
private Animator _animator;
public Transform leftHandObj;
public Transform leftFootObj;
public Transform rightHandObj;
public Transform rightFootObj;
private void Awake()
{
_animator = GetComponent<Animator>();
}
private void OnAnimatorIK(int layerIndex)
{
if (!_animator) return;
// 设置动画权重
_animator.SetIKPositionWeight(AvatarIKGoal.LeftHand, 1f);
_animator.SetIKRotationWeight(AvatarIKGoal.LeftHand, 1f);
_animator.SetIKPositionWeight(AvatarIKGoal.LeftFoot, 1f);
_animator.SetIKRotationWeight(AvatarIKGoal.LeftFoot, 1f);
_animator.SetIKPositionWeight(AvatarIKGoal.RightHand, 1f);
_animator.SetIKRotationWeight(AvatarIKGoal.RightHand, 1f);
_animator.SetIKPositionWeight(AvatarIKGoal.RightFoot, 1f);
_animator.SetIKRotationWeight(AvatarIKGoal.RightFoot, 1f);
if (leftHandObj != null)
{
// 设置左手根据目标点而旋转移动父骨骼节点
_animator.SetIKPosition(AvatarIKGoal.LeftHand, leftHandObj.position);
_animator.SetIKRotation(AvatarIKGoal.LeftHand, leftHandObj.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 (rightFootObj != null)
{
// 设置右脚根据目标点而旋转移动父骨骼节点
_animator.SetIKPosition(AvatarIKGoal.RightFoot, rightFootObj.position);
_animator.SetIKRotation(AvatarIKGoal.RightFoot, rightFootObj.rotation);
}
}
}
}