
Untiy现存的动画系统:Legacy、Mecanim(其余辅助动画系统的有Animation Rigging、 Timeline)
| 动画系统 | 概述 |
|---|---|
| Legacy Animation System | Legacy Animation System:是 Unity 3D 中的传统动画系统,主要基于关键帧动画。在 Legacy Animation System 中,动画数据存储在 Animation Clip 中,可以通过 Animation 组件来播放。这个系统已经逐渐被废弃,但仍然可以用于部分项目 |
| Mecanim | 是 Unity 5 中引入的新一代动画系统,主要基于状态机动画。在 Mecanim 中,动画数据存储在 Animator Controller 中,可以通过 Animator 组件来播放。Mecanim 支持多层混合、过渡动画、IK、可重用的状态机和 Blend Tree 等功能,可以实现更加丰富和复杂的动画效果 |
| Animation Rigging | 是 Unity 2019 中引入的动画绑定系统,主要用于在运行时对角色进行模拟和变形。Animation Rigging 支持多种约束类型,包括 Transform、Rotation、Scale、Parent 等,可以实现更加灵活和自然的动画效果 |
| Timeline | 是 Unity 2017 中引入的时间轴系统,主要用于制作游戏剪辑和动画序列。在 Timeline 中,可以创建和编辑时间轴,将不同的动画片段组合在一起,并在游戏中播放。Timeline 支持多层混合、过渡动画、曲线编辑和事件触发等功能,可以实现更加复杂和多样化的动画效果 |
Unity的Mecanim动画系统,是一套基于状态机的动画控制系统,是一个面向动画应用的动画系统


3dMax/Maya/Blender -> FBX -> Unity
勾选时上一个状态对于的动画片段必须被播放到末尾,才允许这个过渡被触发,不勾选可以在任意时刻进行过渡
打断来源,允许该过度被来自CurrentState或NextState的其它过度打断 被CurrentState打断则发生了跳转,NextState的指向被改变(例如受击打断了攻击) 被NextState打断则发生了跃进,动画迅速完成了两个状态的过度(例如从站立状态快速过度到冲刺态,奔跑状态被越过)
针对CurrentState出发的过渡,是否只允许比当前过渡优先级高的过渡打断该过渡
动态修改State里的AnimatorClip 不支持,只能用 AnimatorOverrideController 去实现 clip 动态替换 方法:运行时生成 AnimatorOverrideController 类,动态换掉动画状态机
Animator animator = GetComponent<Animator>();
AnimatorOverrideController overrideController = new AnimatorOverrideController();
overrideController.runtimeAnimatorController = animator.runtimeAnimatorController;
overrideController["name"] = newAnimationClip;
animator.runtimeAnimatorController = overrideController;注意:
deltaPosition:相对上一帧的位置变化量(必须允许根运动才能被计算)
deltaRotation:相对上一帧的角度变化量(必须允许根运动才能被计算)
void OnAnimatorMove()
{
var transform1 = transform;
transform1.position += animator.deltaPosition;
transform1.rotation *= animator.deltaRotation;
}动画分层我的理解有点像PS的画布、Unity的Canvas,一层又一层,通过叠加模式进行叠加,最后表现出混合后的动画
BlendTree的作用是将多个动画状态混合成为一个动画状态,并通过动画参数来影响状态的输出结果 使用BlendTree的目的是应对状态机的高耦合导致的低扩展缺点,尤其是在人物运动相关的动作(前后左右的行走奔跑)这类繁多的动作
IK (inverse kinematics) 反向动力学,用来解决模型动作跟随问题。 比如人物骑在一个马上面,手要随着马律动 Unity提供OnAnimatorIK() 回调,用来设置IK位置和权重,IK支持左右脚和左右手
public enum AvatarIKGoal{
LeftFoot,
RightFoot,
LeftHand,
RightHand
}条件:
using UnityEngine;
public class TestAnimatorIK : MonoBehaviour
{
[Range(0, 1)]
public float weight = 1; // IK权重
public Transform rightHandFollowObj; // IK跟随的物体
public Transform leftHandFollowObj;
public Animator animator;
private void SetIK(AvatarIKGoal iKGoal, float weight, Transform trans)
{
if (trans)
{
animator.SetIKPositionWeight(iKGoal, weight);
animator.SetIKRotationWeight(iKGoal, weight);
animator.SetIKPosition(iKGoal, trans.position);
animator.SetIKRotation(iKGoal, trans.rotation);
}
}
private void OnAnimatorIK(int layerIndex) {
if (animator)
{
SetIK(AvatarIKGoal.RightHand, weight, rightHandFollowObj);
SetIK(AvatarIKGoal.LeftHand, weight, leftHandFollowObj);
}
}
}通常在游戏中可能出现一下情况:角色必须以某种方式移动,使得手或脚在某个时间落在某个地方(例:角色可能需要跳过脚踏式或跳跃并抓住顶梁)
using UnityEngine;
using System;
[RequireComponent(typeof(Animator))]
public class TargetCtrl : MonoBehaviour {
protected Animator animator;
public Transform jumpTarget = null;
void Start()
{
animator = GetComponent<Animator>();
}
void Update()
{
if (animator)
{
if (Input.GetButton("Fire1"))
{
animator.MatchTarget(jumpTarget.position, jumpTarget.rotation, AvatarTarget.LeftFoot, new MatchTargetWeightMask(Vector3.one, 1f), 0141f, 0.78f);
}
}
}
}自动调整GameObject的位置和旋转。
调整GameObject的位置和旋转,以便当前状态处于指定的进度时,AvatarTarget 到达 matchPosition。目标匹配仅适用于基础层(索引 0)。 一次只能排队一个匹配目标,并且必须等待第一个匹配目标完成,否则将丢弃目标匹配。 如果调用MatchTarget的开始时间小于剪辑的当前标准化时间并且剪辑可以循环,MatchTarget将调整时间以匹配下一个剪辑循环。例如:开始时间 = 0.2,当前标准化时间 = 0.3,则开始时间将为 1.2。必须启用Animator.applyRootMotionMatchTarget 才会有效。

Playables API 是动画系统底层接口,Animator是基于 Playables API 的封装。
在短平快的开发上,基本不需要用到 Playables API。Animator 就基本够用了。
Playables API 灵活度很高,但是有一定开发门槛和学习成本。
除非是动作游戏,射击游戏等有丰富的动画需求的项目,Animator无法满足需求,或者项目有高度定制动画需求倾向,或者动画性能瓶颈,才会去基于 Playables API 去定制针对项目的动画系统。
可视化插件:Unity - Manual: The PlayableGraph Unity - Manual: Playables API 官方实例:Unity - Manual: Playables-Examples Playable API:定制你的动画系统 Playable API_弹吉他的小刘鸭的博客-CSDN博客
由于射线检测位置是从人物的中心,而高度我们只能获取到BoxCollider的Size高度,因此从中心到人物左手,从Box顶部到手真正需要放的位置,我们使用了两个偏移量保证左手位置的正确
角色被隐藏后,状态机也完全停止了,这个时候对状态机的参数修改会失效,因此需要一个列表用来记录需要恢复的参数。
Hierarchy上的一个选项,Optimize Transform Hierarchy,可以删除transform节点,减少CPU计算,这个优化可以在CPU瓶颈下,进行优化