第5章
动画系
统


Unity的动画系统基于动画剪辑(AnimationClip)的概念,动画剪辑包含特定对象应如
何随时间改变其位置、旋转或其他相关属性的相关信息。AnimatorControler作为动画状
态机,负责集中管理由动画剪辑对应的所有状态,负责跟踪当前应该播放哪个剪辑及动画应
该何时改变或混合在一起。通过本章的学习,读者将能够熟练掌握Animator的使用方法
和技巧,为创建生动形象的游戏动画打下坚实的基础。

5.动画剪辑
1 

Unity的动画系统基于关键帧动画的概念,多个关键帧构成了动画的连续变化,这些关
键帧动画信息存储于动画剪辑资产中。

通过编辑动画剪辑,开发者可以创建、修改和管理其中的关键帧,从而实现角色、物体或
其他游戏元素的动画效果。

动画剪辑在Animation窗口中进行编辑,该窗口通过菜单Window/Animation/Animation 
或者快捷键Ctrl+6打开,如图5-1所示。


图5-1 Animation编辑窗口

开发者可以在时间轴上设置关键帧,然后系统会根据这些关键帧来自动计算中间帧,从
而创建出平滑的动画效果。

关键帧可以通过手动创建,也可以通过进入录制模式录制关键帧,本节将介绍这两种关
键帧创作方式。


112 

5.1 
录制关键帧
1.
观察Animation窗口,可以看到左上角Preview按钮的右侧有一个红色的按钮,单击该
按钮即可进入录制模式,如果在录制模式下对场景中的对象进行改动,系统则会自动在时间
轴中的当前位置生成关键帧,记录修改的属性。

例如,在示例场景中创建一个Cube物体,为其创建一个新的AnimationClip资产,进
入录制模式后,在0:00 时间点将其坐标
x 
值修改为5,在1:00 时间点将其坐标
x 
值修改为
10,可以看到,系统自动在时间轴中的对应位置生成了关键帧,如图5-2所示。


图5-2 录制关键帧

录制完成后,再次单击录制按钮退出录制模式,单击“播放”按钮,即可进入预览状态,从
而可以预览动画。

5.2 
创建和编辑关键帧
1.
在非录制模式下,如果要在指定的时间点记录对象属性,则需要先手动添加关键帧再进
行记录,关键帧可以通过单击Addkeyframe 按钮进行添加,也可以在时间轴中右击并选择
AddKey选项进行添加,如图5-3所示。


图5-3 添加关键帧

添加关键帧之后可以在左侧的属性列表中编辑对应属性的值,也可以单击窗口下方的
Curves按钮,进入曲线编辑窗口,通过编辑曲线的方式编辑属性值,如图5-4所示。

5.3 
外部导入的动画资产
1.
动画剪辑可以是在Unity中创建的资产,也可以是由外部导入的fbx文件包含的资产。


113
图5-4 曲线编辑窗口

外部导入的动画剪辑可能包括美术工作人员在3dsMax、Maya或Blender中创建的动画, 
也可能是来自第三方库的动画集,如图5-5所示。


图5-5 外部导入的动画资产

ImportAnimation选项默认为勾选状态,表示导入外部动画,如果取消勾选,则动画资
产将不会被导入。

打开Rig选项卡,可以看到动画类型有
None、Legacy、Generic和Humanoid共4种
类型,如图5-6所示。Legacy是旧版本中使
用的动画类型,已经不推荐使用。Generic表
示通用动画,Humanoid表示人形动画,它们
的核心区别在于,Humanoid类型的动画可
以通过骨骼重定向复用不同的人物角色动
画,并且支持IK 功能,

IK 功能将在后续的章
节中进行介绍。
在Animation选项卡中可以对动画剪辑进行裁剪,如图5-7所示,Start表示起始帧, 
End表示结束帧。假设将Start设置为0,将End设置为15,表示截取0~15 帧的动画。

图5-6 动画类型

1 14 
图5-7 动画裁剪
5.2 动画状态机
动画状态机(AnimatorController)资产通过菜单Assets/Create/AnimatorController 
创建,双击该类型资产或者通过菜单Window/Animation/Animator可以打开Animator窗
口,在该窗口中可以对动画状态机进行编辑。
5.2.1 Animator窗口
Animator窗口分为两个主要部分,分别是左侧的Layers与Parameters编辑区域和右
图5-8 参数类型
侧的状态编辑区域。
动画参数在Parameters 视图中进行编辑,包含
Float、Int、Bool和Trigger共4种参数类型,如图5-8所
示。在脚本中访问这些参数并向其赋值,即可实现状态间
的切换,4种类型参数对应的脚本中设置参数值的方法分别
是Animator类中的SetFloat()、SetInteger()、SetBool() 
及SetTrigger()方法,代码如下: 
public void SetFloat (string name, float value); 
public void SetFloat (string name, float value, float dampTime, float deltaTime); 
public void SetFloat (int id, float value); 
public void SetFloat (int id, float value, float dampTime, float deltaTime); 
public void SetInteger (string name, int value); 
public void SetInteger (int id, int value); 
public void SetBool (string name, bool value); 
public void SetBool (int id, bool value); 
public void SetTrigger (string name); 
public void SetTrigger (int id); 
可以看到,除了可以通过参数名称设置参数值外,还可以通过参数id设置参数值,参数
id通过Animator类中的StringToHash()方法获取,代码如下: 
public static int StringToHash(string name); 
在Layers视图中可以创建不同的动画层,如图5-9所示,使用动画层可以管理身体的
不同部位。例如当前有行走和射击两个动画,通过将行走动画放到下身层,将射击动画放到

115 

上身层,可以实现边行走边射击的动画融合效果。


图5-9 动画层

单击动画层右侧的齿轮按钮打开该层的设置弹窗,Weight用于设置该动画层起作用的
权重值,AvatarMask用于设定身体起作用的部位,该类型资产通过菜单Asets/Create/
AvatarMask进行创建。Blending用于设置如何应用该动画层,包含Overide和Additive 
两种类型,这决定了该层动画是替换上层动画还是叠加到上层动画。Sync用于设置是否同
步其他层的状态机,开启后,该层的状态机与要同步的层的状态机具有相同的结构,但是实
际使用的动画剪辑可以不同。IKPas 
用于设置是否启用IK 。

5.2 
动画状态
2.
动画状态是动画状态机的基本组成部分,通过右击空白区域,选择CreateState/Empty
进行创建,如图5-10所示,也可以通过将动画剪辑拖入状态编辑区域进行创建。


图5-10 Animator窗口

选中某个动画状态,在Inspector窗口中查看状态的属性,如图5-11所示,属性详解见
表5-1。


116
表5-
1 
动画状态属性

属性

Motion 

Sped 
MotionTime 

Miror 

CycleOfset 

FootIK 

WriteDefaults 

Transitions 

详解

该动画状态所引用的动画剪辑

该动画状态的默认播放速度,可以通过参数的形式进行修改

用于播放该动画状态的动作的时间

是否启用镜像动画(仅用于人形动画),例如为一个向左行走的动画开启镜像,得到的
是向右行走的动画

时间偏移量,当动画被设置为循环播放时,该属性将决定从动画的哪部分开始播放, 
例如当时间偏移量为0时表示从头开始播放,当时间偏移量为0.

5时表示动画从其
一半的位置开始播放

是否启用脚部IK(仅用于人形动画) 
用于控制Animator是否将未动画化的属性写回其默认值

源自该动画状态的过渡列表

当角色的行为十分复杂时,状态机将非常庞大,在这种情况下通常会使用子状态机对状
态进行管理。子状态机通过在状态编辑区域的空白区域右击并选择CreateSub-State 
Machine进行创建,如图5-12所示。双击子状态机即可进入子状态机的编辑窗口,窗口顶
部会显示当前正在编辑的子状态机。


图5-11 动画状态图5-12CreateSub-StateMachine 

5.3 
动画过渡
2.
状态之间的带有箭头的连线是过渡线,表示状态过渡,单击过渡线,在Inspector窗口中
编辑状态过渡的属性,如图5-13所示,这些属性决定了状态机从一种状态过渡到另一种状
态的混合时长,以及应该在什么条件下触发过渡,例如从Idle状态过渡到Move状态的过渡
条件是当Move参数变为true时。

动画过渡的属性详解见表5-2。


117
属性

HasExitTime 

ExitTime 

FixedDuration 

TransitionDuration 

TransitionOfset 

InteruptionSouce 
OrderedInteruption 

图5-13 动画过渡

表5-
2 
动画过渡属性

详解

当动画过渡不依赖过渡条件时启用此选项,表示经过指定的标准化时间后进行
过渡

当勾选HasExitTime时,此值表示进行过渡的标准化时间

当值为true时表示过渡时间以秒为单位,当值为false时表示过渡时间以源状态
的标准化时间进行表示

过渡持续时间,当FixedDuration为true时此值表示秒数,当FixedDuration为
false时此值表示标准化时间

过渡到的目标状态的起始播放时间偏移值

控制过渡中断的类型

确定当前过渡是否可在不考虑顺序的情况下被其他过渡中断,默认值为true 

InteruptionSouce的类型及详解见表5-3。

表5-
3 
InteruptionSouce详解

类型

None 

CurentState 

NextState 

CurentStatethenNextState 

NextStatethenCurentState 

详解

不添加任何过渡

将当前状态的过渡排队

对下一状态的过渡进行排队

将当前状态的过渡排队,然后将下一状态的过渡排队

将下一状态的过渡排队,然后将当前状态的过渡排队


118 

如果将InteruptionSouce设为None,则在状态过渡期间不会因任何其他状态过渡的
触发而中断,但是如果将其设为CurentState,则在状态过渡期间可能会因为源状态上的一
些状态过渡触发而中断,为了更深入地理解,在示例状态机中添加Jump、Talk两个新状态, 
如图5-14所示,选中Idle状态,过渡优先级设置如图5-15所示。


图5-14 状态机


图5-15 过渡优先级

在Idle至Move的状态过渡中,将InteruptionSouce设为CurentState,那么在该状
态过渡期间,如果Idle至Talk的状态过渡被触发,则Idle至Move的状态过渡将保持不间
断,但是,如果Idle至Jump的状态过渡被触发,则Idle至Move的状态过渡将立即中断,开
始向Jump状态过渡。

当然,以上是在OrderedInteruption属性为true的前提下,如果OrderedInteruption 
属性为false,则Idle至Talk、Idle至Jump均会中断Idle至Movc的状态过渡,如果它们在
同一帧中触发,则状态会向Jump过渡,因为Idle至Jump具有更高的优先级。

如果将InteruptionSouce设置为NextState,则Idle至Talk、Idle至Jump不会中断
Idle至Move的状态过渡,但是当Move至Jump的状态过渡被触发时,Idle将立即开始向
Jump状态过渡。

CurentStatethenNextState、NextStatethenCurentState的类型则是为了更好地
控制,在这种情况下,状态机将先分析前一种状态的过渡再分析后一种状态的过渡。例如当
设置为CurentStatethenNextState时,在Idle至Move的状态过渡期间,如果Idle至Talk、
Idle至Jump、Move至Jump的状态过渡同时被触发,则状态机会开始向Jump状态过渡。

2.混合树
5.4 
混合树用于实现多个动作之间的平滑混合,每个动作对最终效果的影响由混合参数决


119 

定。混合树通过在空白区域右击并选择CreateState/FromNewBlendTre 
进行创建。

例如,当前有Idle、Walk、Run共3个动画,分别是角色的静止动画、行走动画和奔跑动
画,为了取得从静止到走跑或者从走跑到静止的良好的混合效果,将它们放在一个混合树
中,通过一个float类型的参数进行控制,如图5-16所示。


图5-16 混合树

选中混合树,可以在检视窗口为各个动画设置阈值,如图5-17所示,当参数为0时,角
色将处于静止状态,当参数从0逐渐过渡到2时,角色也将从静止动画逐渐过渡到行走动
画,当参数逐渐过渡到3.角色动画也将逐渐过渡到奔跑动画。

75时, 


图5-17 混合树阈值

以上是1D混合类型的混合树,假设角色有不同方向的移动动画,例如向前走、向左前
方走、向右前方走等,移动方向需要通过两个参数进行控制,如图5-18所示,此时便需要2D 
混合类型的混合树。

2D混合类型有多种,包括2DSimpleDirectional、2DFrefoomDirectional和2D 
FreformCartesian,它们具有不同的用途。

2DSimpleDirectional适用于运动表示不同的方向,但是在同一方向上不会有多个运
动的情况。假设在一个方向上有多个运动,例如向前移动有向前走和向前跑,这种情况适合
使用2DFreformDirectional混合类型。2DFreformCartesian适用于运动不表示不同方
向的情况,两个参数表示不同的概念,例如速度和角速度。

PosX和PosY的取值可以通过ComputePositions下拉菜单选择不同的方式进行计
算,如图5-19所示。VelocityXZ表示根据运动的VelocityX和VelocityZ分别设置PosX 


120
图5-182DSimpleDirectional 

和PosY,SpedAndAngularSped表示根据运动的角速度(弧度/秒)和速度分别设置Pos 
X和PosY,而XPositionFrom表示仅根据其中一项设置PosX,PosY保持不变,Y 
PositionFrom同理。


图5-19ComputePositions 

5.动画事件
3 

动画事件通常用于在动画播放的特定时间点触发某些操作,例如播放声音、切换动画状
态、调用函数等。动画事件的实现方式有多种,下面介绍两种动画事件的实现途径。