【Unity学习笔记】Introduction to 3D Animation Systems
1. 课程概览与核心概念
1.1 课程概览
1.1.1 概览
在本课中,您将学习Unity动画系统的基本知识,并用其创建动画以提升游戏体验。
1.1.2 课程对象
Unity动画系统的初学者,需具备一定的Unity使用经验和初步C#代码知识。
1.1.3 课程结构
(1)Unity动画系统简介
了解Unity动画系统的核心概念,巩固对课程实例的理解。
(2)使用资源
·创建并编辑动画片段
·设置骨骼
(3)动画控制器
了解动画控制器中的动画融合、状态机和动画图层。
(4)动画脚本简介
一般人形动画脚本的编写
1.1.4 如何完成本课
·顺序阅读
按照章节顺序学习,全面理解Unity的动画系统,建议新手采用这种方法。
·模块学习
专注于希望学习的特定部分。
1.1.5 下载课程资源
1.2 核心概念:动画数据
1.2.1 概述
在本课中,您将学到在Unity中创建动画的两个核心概念:动画数据和动画融合。
1.2.2 开始之前的准备工作
1.2.3 动画数据与动画片段简介
动画数据存储在名为动画片段的资源中。动画片段可以存储任何游戏物体的动画,它是Unity动画系统的基础材料。
1.2.4 动画片段中动画数据的两个部分
值:通常由动画曲线表示。动画曲线包含了物体动画变化方式的信息。
绑定(Bindings):将值与特定的物体区域或部件联系起来的方式,包括从层级到物体变形部件的路径以及从变形部件到特定区域的路径。
值和绑定是一对一的关系。
1.2.5 打开动画片段范例
1.2.6 了解动画数据与动画曲线
1.3 核心概念:动画融合
1.3.1 概览
本课介绍了Unity动画核心概念之二:动画融合。
1.3.2 开始之前的准备工作
1.3.3 动画融合简介
当同时播放多个动画片段时,Unity会对其进行融合。融合时,每段动画都有相对权重,以计算其对最终动画的影响。最常见的计算方式是加权平均。
1.3.4 调整动画示例的权重
打开本节教程资源并加载场景CoreConcepts。
调整两段动画的权重:
选择Cube>在检查器的Blending Example组件中,将Circle Weight调整为0(Square权重将自动变为1)
1.3.5 动画控制器的作用
动画控制器可以控制动画片段何时开始播放以及如何与其他动画片段融合。它结合了由特定游戏物体播放的所有动画片段,并规定了控制动画回放的逻辑。
1.3.6 了解动画控制器
打开动画控制器CubController>打开节点Blend Tree(组合多个动画片段的状态,将输入权重赋予动画片段并决定了它们的融合方式)
动画控制器
·是一组逻辑状态,包含一个或多个动画片段
·动画控制器通过路径联系这些状态,决定该状态下当前播放的动画片段。
·状态之间通过过渡(Transitions)连接,融合了这些状态下的动画片段。
1.3.7 创建动画控制器
点击文件夹AnimatorControllers>创建Animator Controller>重命名为ExampleController
1.3.8 在ExampleController上添加动画片段
打开AnimationClips文件夹>将动画片段Circle和Square拖入Animator窗口
1.3.9 创建新的过渡
点击Circle>右键选择Make Transition>将箭头拉至Square
1.3.10 设置过渡
退出时间
点击过渡箭头>展开Settings下拉菜单>将Exit Time改为1.5
过渡时机
将Transition Offset改为0.5>将Transition Duration改为2
1.3.11 检查调整后的动画
将ExampleController拖入Cube检查器的Controller属性框>移除Blending Example组件
1.3.12. 总结
2. 运用资源
2.1 动画窗口:功能与设置
2.1.1 概览
在本节中,将加深对绑定和值在动画窗口中的显示方式的理解,并了解在动画窗口中浏览动画片段的基本知识。
2.1.2 课程准备
2.1.3 回顾:动画片段中的数据
·绑定(Bindings)显示了游戏物体或其组成部分在动画回放中的变化区域。
·值(Values)显示了给定时间哪个区域应该变化。通常,这些值为随着时间推移而变化的浮点值,表示为曲线。
·动画窗口显示了与动画片段相关的绑定和值。
·你可以使用动画窗口编辑动画片段的绑定和值。
2.1.4 分析动画示例
打开本节示例中的场景>AnimationClips>双击动画片段LightFlicker
2.1.5 编辑导入的动画片段
如果你希望编辑作为模型一部分导入的动画片段,可以复制该片段后对新片段进行编辑。片段副本与模型将没有联系,因此不会在模型导入设置变化时发生变化。
打开本节资源中的AnimationClips>HumanoidCrouch>点开模型的下拉菜单,选择一个动画片段>Ctrl+D复制片段
隐藏只读属性:在Animation窗口中打开时间线旁边的菜单>显示只读属性
2.1.6 动画片段的环境
在动画窗口中浏览动画片段有两种方法:作为资源浏览和在环境中浏览。选择的浏览方式将决定编辑动画片段的方式。
作为资源浏览:
动画窗口中不包含用于播放动画的游戏物体,因此不能向动画片段中添加动画曲线。
在项目窗口中选择动画片段并打开。
在环境中浏览动画片段:
通过游戏对象层级浏览动画片段时,动画窗口将处于特定环境中。这意味着你可以添加动画曲线。
·在层级窗口中选择带有动画控制器(含动画片段)的游戏物体。在动画窗口中可以看到动画控制器引用的片段,你可以访问需要环境的设置。
如果没有环境,就无法预览动画片段。
2.1.7 动画片段环境:街灯示例
单独浏览动画片段时,无法编辑动画属性。在层级窗口下点击带有动画器的游戏物体,即可编辑动画属性(此时可以检测到环境)。
2.1.8 复习动画窗口模式
动画窗口概览:动画片段由两部分组成:值和绑定。
关键帧:关键帧包含动画曲线在特定时间的值以及如何插值的信息。
关键帧清单(Dopesheet)和曲线模式:在动画窗口中浏览动画片段的两种方式。
改变模式:点击下方标签。
改变速度:时间轴可以按秒或按帧显示。在Show Sample Rate窗口可以更改预览窗口中包含的帧数或秒数。
2.1.9 复习动画窗口工具栏
在资源模式下浏览动画片段时,部分按钮将不会激活。
预览模式:预览模式下,时间轴和预览的属性在检查器中将变为蓝色。也可以点击并拖拽曲线上方的时间轴,进入预览模式。
录像模式:录像模式下,时间轴和预览的属性在检查器中将变为红色。在录像模式下对属性做的更改将被录入动画片段。
时间轴播放头(playhead):标明了时间轴上被预览的具体点。
播放按钮:只有在环境中才能预览动画片段。
倒回开头、倒回、快进、和快进到最后:
当前帧:在播放按钮行的最右侧,可以手动输入。
2.1.10 选择或创建动画片段
在动画预览窗口左上下拉菜单可以直接创建新动画片段,创建的动画片段将自动加入当前使用的动画控制器。
2.1.11 过滤动画片段的动画曲线
一般来说,动画越复杂,动画曲线越多。过滤动画曲线的步骤:在层级窗口中选择相应游戏物体(或子物体)>点击选择过滤器(准星图标)
2.1.12 添加关键帧和动画事件
2.2 编辑动画片段
2.2.1 概览
2.2.2 开始之前
2.2.3 回顾:动画片段的数据
2.2.4 在LightFlicker动画片段上增加绑定
Window>Animation>Animation
在层级中选择StreetLamp>在窗口左侧选择Add Property
SpotLight>Light>Color
在子游戏物体中有Is Active属性,但根游戏物体中没有。这是为了阻止根物体被禁用,因为这会禁用动画器并导致一系列问题。
2.2.5 编辑动画曲线的值
添加Color属性后,会增加四条动画曲线,即R、G、B和A。
编辑值时,先将播放头移动到当前时间,然后调整数值。如果之前没有关键帧,会自动创建关键帧。
或者,在曲线模式下可以直接拖拽关键帧或者右键单击关键帧并选择Edit Key。
2.2.6 编辑新动画曲线的值
2.2.7 复习关键帧的设置
两个关键帧之间任意时点的值是使用关键帧切角计算出来的。每个关键帧都有两个切角:入切角(in-tangent)和出切角(out-tangent)。作为例外,第一帧和最后一帧的入切角和出切角彼此相连。
关键帧预设
在关键帧上单击右键可唤出预设菜单
·自动收敛(Clamped Auto):动画曲线不会超出关键帧的值并将平滑逼近该值。
·自动(Auto):这是为Unity3.x创建的动画片段准备的老版设置。
·自由平滑(Free Smooth):该设置是获得平滑曲线的最佳方式。
-平坦:切线为水平的自由平滑变型。
·折线:左右切线不平行且方向独立。
-自由:折线切角的通常选项。
-线性:随着动画曲线逼近关键帧,切线倾向于变成直线。如果临近切线都是线性的,则两个关键帧之间的动画曲线为直线。
-固定:在下一个关键帧之前,动画曲线的值等于前一个关键帧的值。
·加权:该选项可以附加到其他设置上。它允许调整切线长度。
2.2.8 用录像模式创建动画
录像模式开启时,对层级界面中动画化游戏物体的任何更改都会录制下来。
(类似于MMD)
2.2.9 一次操作多个关键帧
关键帧清单模式
该模式下,纵轴不显示值的变化。拖拽选择框只会移动关键帧在时间轴(横轴)上的位置。
也可以拖拽选择框两侧的蓝条,水平缩放选择框,使关键帧靠近或拉远。
波纹编辑(Ripple editing)
如果选择范围外的关键帧随变化而移动,那么就是波纹编辑。这是因为变化产生了波纹效应。(快捷键:R(只能用一次))
曲线模式
支持纵向移动和缩放。
2.2.10 编辑拍球动画
编辑关键帧时,如果按住Shift再点击关键帧,在已选中状态下会将其移除。
2.2.11 小结
2.3 模型动画导入设置
2.3.1 概览
从数字内容创建(DCC)程序导入模型时,它的动画设置分为两部分:
·模型特定设置:影响随该模型导入的所有动画。
·动画特定设置:影响随该模型导入的各动画。
2.3.2 开始之前
2.3.3 模型动画基础
模型由许多三角面组成,但三角面不是各自独立移动,而是依赖于骨骼的运动。骨骼使用动画数据运动,然后根据骨骼的位置和旋转计算出相关顶点的运动。骨骼层级及其影响网格的方式构成了骨架(Rigs)。
两类变形
正向运动学(Forward kinematics)
较低层级骨骼的运动依赖于较高层级骨骼的运动。
逆向运动学(Inverse kinematics)
骨骼链末端的位置和旋转通过算法影响骨骼链远端骨骼的位置和旋转。
2.3.4 导入约束与动画
约束是对关节运动的限制。如果选择导入约束,它将成为实例化模型的一部分。如果选择不导入动画,将没有更多设置可调整,也不会创建动画片段。
2.3.5 烘焙动画
决定了动画是作为IK导入还是通过烘焙过程转化为FK。
动画片段以FK格式储存数据。因此带有IK数据的模型导入时应该进行烘焙,将数据从IK转换为FK。如果导入动画是用Maya、3DS Max或Cinema 4D创建,或者导入动画带有IK或模拟数据时,可以启用烘焙动画。
2.3.6 动画曲线重新采样
重新采样选项只适用于一般骨架(generic rigs)模型。该设置决定了带旋转欧拉角的导入动画是否将其转换为四元数角(quaternion angles)。
一般来说,所有带欧拉角的导入动画都应该进行重新采样,除非转换中出现问题(比如旋转角度大于180度)。
2.3.7 优化动画大小
动画压缩(Animation Compression)设置决定了在硬盘和内存中如何压缩动画。
·关闭:不进行压缩。
·关键帧压缩(Keyframe Reduction):去掉值类似的关键帧。
·最优压缩:将动画压缩得尽量小。
选择最优压缩时,Unity首先试图使用关键帧压缩,如果动画曲线的值变换得比较频繁,那么帧压缩的效果不会很好。此时一种简化表示方法是在各帧的值之间采用线性插值法。这将把动画片段压缩到最小,并影响动画效果。
决定是否移除关键帧时的默认容错率为0.5%。
2.3.8 调整自定义属性
这是针对导入动画额外属性的高级设置。
2.4 剪切导入的动画片段
2.4.1 概览
剪切动画(cutting animation)最常用于动作捕捉(mocap)数据,但也可以用于调整任何导入动画。
2.4.2 开始之前
2.4.3 剪切与设置动画片段
2.4.4 打开动画片段
在项目窗口中选择HumanoidRun模型,然后在检查器中选择Animation标签
2.4.5 了解动画时间轴
通过调整把手或直接输入起始帧/结束帧数据,可以在动画片段中选定范围。
2.4.6 了解循环质量标示灯(loop quality traffic lights)
·绿灯表示循环良好。
·黄灯表示循环尚可,可能适合也可能不适合您的环境。
·红灯表示循环糟糕。
起点和终点的所有设置均应为绿灯。
2.4.7 播放完整动画
在检查器中找到预览窗格>按播放键
2.4.8 了解示例循环标示灯
·图中的水平线代表模型没有动作,可能是因为动作捕捉录制不当。不要在动画片段中包括它们。
·在动作起点,模型身体倾斜程度比跑步时大,这对于跑步动画来说并不理想。
·通过观察,发现有一小段动画(大概10秒)可用。
2.4.9 创建动画剪辑
将起始手柄拖到第290帧至第330帧之间>将结束手柄拖到适当位置>播放测试
2.4.10 启用循环时间
2.4.11 启用循环姿势(Loop Pose)
循环姿势设置改变了动画片段中关键帧的值,使开始和结束时的姿势匹配。
简单地说,循环姿势用于确保动画在开始和结束时不会出现导致动画抖动的突然变化。
近似计算公式
新值=初始值-标准化时间×(结束值-初始值)
2.4.12 了解周期抵消(Cycle Offset)设置
周期抵消调整的是动画片段从您选择的帧范围中实际开始的时间。
它以标准化时间衡量,例如,0.2表示将从所选帧范围的20%处开始播放动画片段。
独立动画片段一般无需考虑此设置,但混合类似动画时,则有必要考虑进行此设置。
比如,人形动画要确保待混合的所有动画片段在同一个标准化时间的腿部位置类似。一种简单方法是确定一个标准,即每个动画片段开始时腿应该在周期的哪个位置。
2.4.13 设置动画的循环偏移(Cycle Offset)
移到动画预览的侧面视图>将播放头移到显示预定姿势的位置上>将下方显示的百分比数值填入Cycle Offset
2.4.14 总结
2.5 设置导入动画片段的根运动
2.5.1 概览
本课将在混合动画的基础上探索根运动在创建现实感动画中的作用。
2.5.2 开始之前
2.5.3 根运动简介
根节点被用于定义根运动。根运动是指动画导致游戏物体与前一个位置产生偏移,而不仅仅是绝对值变化。这意味着运动看上去将更真实,因为它是基于动画本身而不仅仅是脚本。
缺点:动画运动的一致性不如脚本运动(scripted movement)。
2.5.4 检查当前的根运动
在项目窗口中选择HumanoidRun>Animation标签>找到Average Velocity和Average Angular Y Speed信息(仅适用于人形)
发现当前模型具有右转角速度、y轴上的速度和向右侧的速度。这对于动画来讲并不适合。修正方式是将部分根运动要素烘焙到姿势中。这意味着它们将不再影响根运动。
2.5.5 设置根旋转
奔跑动画应该沿直线运动,所以根旋转应烘焙进姿势。
检查器>Root Transform Rotation>启用Bake Into Pose
2.5.6 了解根旋转的来源
目前,根旋转的来源是身体旋转。这意味着根旋转是基于角色身体的面朝向。
如果导入的动画是一般型(generic)而非人型,则可以选择使用根节点朝向而非身体朝向。这是因为一般骨骼没有身体的概念。
2.5.7 调整偏离(Offset)
根旋转偏离是根相对于动画片段开始时的姿势的旋转量。
检查器>Root Transform Rotation-Offset>拖动Offset直至Average Velocity X为0(Offset的值为1.51)
2.5.8 烘焙垂直根运动
检查器>Root Transform Position(Y)>启用Base Into Pose
人形骨骼可以选择垂直根运动基于足部或身体重心。
2.5.9 了解横向根运动
横向根运动控制动画在XZ平面上的运动。
对于仅沿y轴运动或者不移动的动画,我们可以将横向根运动烘焙入姿势。如果你希望让奔跑动画的所有根运动无效,仅用脚本控制,就可以将横向根运动烘焙入姿势。
2.6 完成动画剪辑:其他设置
2.6.1 概览
本节将介绍既适用于人型骨骼又适用于一般骨骼的动画设置。
2.6.2 开始之前
2.6.3 镜像设置
只有人型骨骼动画才有镜像设置。启用后,镜像设置将把动画以角色中心为轴在YZ平面上翻转。例如,从向左跑变为向右跑。
2.6.4 启用叠加参考姿势(Additive Reference Pose)设置
在普通的动画中,动画曲线的值会覆盖每个绑定的默认值。使用叠加动画后,可以在现有动画的基础上进行修改。例如,如果有角色向不同方向倾斜的动画,就可以将这些倾斜叠加在正常跑步的动画上,做出拐弯效果。叠加动画作为相对于参考姿势的delta(小幅变化或微小差异)存储在参数中。
启用Additive Reference Pose>选择用作参考姿势的帧序号。
2.6.5 添加曲线
动画片段导入后,其动画曲线是锁定的,处于只读状态。在编辑中可以添加曲线,这些曲线有别于创建和编辑动画片段时使用的动画曲线。
创建曲线:
检查器窗口>Curves下拉菜单>Add(+)>确定相关动画控制器有与曲线名称相同的参数。
关于循环偏移的注意事项
以这种方式添加到动画片段中的动画曲线不考虑循环偏移,而是和应用周期偏移前的原始动画剪辑同步播放。因此,如果你希望使用预览栏帮助设置曲线的值,应该暂时将Cycle Offset设回零,创建曲线,然后再将Cycle Offset重设为需要的值。
2.6.6 编辑曲线
您可以像往常那样使用曲线编辑器(Curve Editor)编辑动画曲线。点击曲线名称右边的波形图即可打开编辑窗口。
点击预览时间线>点击图标“New Keyframe”>设定关键帧的值。
注意:使用预览窗口时不要忘记将循环偏移设回0。
2.6.7 其他导入指南
·动画事件(见2.7)
·变形与动画蒙版(Avatar Masking)
导入动画片段时可以只使用模型层级中的部分变形。这个过程类似于动画蒙版,但它是以动画片段为基础,不需要资源。(详见2.9)
·覆盖根运动(Overriding Root Motion)
在运动标签中,可以选择覆盖所选骨骼部分的根运动。(详见2.8)
·导入信息
导入信息下拉菜单中不包含设置,但包含可以在导入过程中更改的项目的信息。如果导入动画在Unity中与动画软件中不同,请查看导入信息栏。
2.6.8 总结
2.7 创建和设置动画事件
2.7.1 概览
2.7.2 开始之前
2.7.3 调用带有动画事件的方法
动画事件调用MonoBehaviour脚本中的方法。脚本必须和动画片段播放的动画器挂在同一个游戏物体上。
当以下条件成立时,将激活动画事件并调用其方法。
·前一帧的动画片段标准化时间在动画事件的标准化时间之前。
·当前帧的动画片段标准化时间在动画事件的标准化时间之后。
方法不一定是公共方法,可以有一个参数(浮点、整数、字符串或物体)。
2.7.4 动画事件与环境之间的关系
根据是否存在游戏物体作为环境,动画片段有不同编辑方法。动画事件同理。
不管是否存在游戏物体作为环境,动画事件都可以添加到动画片段中,但创建方式因此而有所不同。
动画事件包括两种信息:调用方法的时间;调用方法的名称。(也可能包括一个参数)
2.7.5 创建有环境的动画事件
小球带有粒子系统(子物体),我们要用它做出弹起灰尘的效果。
动画窗口>选择Curves>全选所有关键帧(Ctrl+A)>按F>将播放头移到小球第一次弹起的时候(第10帧)>点击图标Add event
2.7.6 设置带有环境的动画事件
在检查器的Function下拉菜单中选择PlayParticles()>点击播放
2.7.7 创建不带环境的动画事件
在项目窗口中选择Models>选择模型Ball>在检查器中选择Animation标签>打开Events下拉菜单>在预览窗口中找到第10帧>点击按钮Add Event,创建无环境的动画事件。
2.7.8 设置不带环境的动画事件
在Function一栏中输入“PlayParticles”(名称必须与调用的方法完全匹配。)
2.7.9 总结
2.8 设置通用骨架
2.8.1 概览
骨架定义了导入模型的结构,并被用来定义动画的播放方式。
2.8.2 开始之前
2.8.3 打开骨架标签
打开案例模型Ellen>点击骨架(Rig)标签
唯一可设置的是动画类型(Animation Type)。如果模型不带动画,此项可以默认为无。
2.8.4 了解动画类型设置
旧式(Legacy):此项是为了确保与4.X之前版本的兼容性。
通用(Generic):最常见的动画类型。
人型(Humanoid):导入角色为人型,且带有由另一个不同层级结构的人型模型播放的动画,或者需要用该模型播放不同层级结构的人型模型的动画,或者你希望使用内置人型功能,例如手臂或腿部IK或目标匹配。(详见2.9)
本例中选择“通用”类型。
2.8.5 创建新的Avatar
Avatar是代表模型骨架的资源。根据骨架是通用型还是人型,它将呈现不同形式。
一些动画功能(例如动画蒙版)需要用到Avatar。常见的一种用途是对于播放动画的模型创建Avatar,并让包含动画数据的模型使用它。
创建Avatar
Rig标签>Avatar Definition>Create From This Model>Apply
2.8.6 选择根节点
动画类型选择“通用”后,下一步是选择根节点。
根节点简介
根节点被用于定义动画的根运动。根运动是动画导致游戏物体偏离之前的位置而不仅仅是移动绝对距离时的运动。
例如,如果游戏物体的动画是沿z轴向前运动,那么在根节点模式下,当动画循环播放时,游戏物体将不断沿z轴前进。
没有根运动时,只要动画循环,游戏物体就会返回开始位置并再次沿z轴向前运动。根节点被用作这个运动的参考。
本例的根节点应为Ellen_Skeleton/Ellen_Root。
2.8.7 设置皮肤权重
皮肤权重设置让我们可以调整顶点皮肤受多少根骨头的影响。默认是4根,建议在多数情况下保持该设置不变。
需要更改该设置时,可以将Standard(4 bones)改为Custom。
最大骨骼/顶点设置
2.8.8 优化模型游戏物体
当模型层级十分复杂时,可能有许多游戏物体只是为了定义皮肤网格的顶点位置。启用优化游戏物体后,所有无组成部分的游戏物体将被移除。
显示额外变形(Expose Extra Transforms settings)设置
有时,有必要保留启用优化游戏物体后会被移除的游戏物体。例如,对于某个穿戴可拆卸武器的角色,可能需要显示“胸部”游戏物体,以便将武器附在上面。为了保留游戏物体,就需要使用显示额外变形(Expose Extra Transforms)设置。
检查器>启用Optimize Game Objects>展开Extra Transforms to Expose下拉菜单>展开各节点菜单,启用Ellen_Chest节点>点击Apply并将模型拖入层级窗口,将其实例化
此时在层级窗口中展开模型游戏物体,该骨骼中将不再有Ellen_Body和Ellen_Chest以外的子物体。
2.8.9 创建并应用Avatar蒙版(Avatar Masks)
Avatar蒙版是一种防止动画数据被写入绑定(binding)的方式。对于人型Avatar和泛型Avatar,Avatar蒙版的工作原理不同,但整体效果相同:不会使用加蒙版来源的变形数据。
创建Avatar蒙版:在项目窗口的创建菜单中选择Avatar Mask
泛型Avatar的Avatar蒙版
在变形菜单中,选中的项将不会加蒙版。
应用Avatar蒙版
在两种不同情况下,应该应用Avatar蒙版:
·在导入过程中导入动画片段时,防止特定变形的动画数据添加到该动画片段中。
·对于动画控制器中的动画图层,防止特定变形的动画数据添加到由此得到的动画控制器所有图层的混合图层中。这些Avatar蒙版必须作为资源创建,但独立于其他Avatar蒙版运行。
2.8.10 总结
2.9 设置人形骨架
2.9.1 概述
·将骨骼映射到变形,并使用自动映射简化这个过程。
·应用t-pose作为人形模型的参考姿势
·改变每块肌肉的设置,以及这对最终动画的影响
2.9.2 开始之前
2.9.3 复习:人形动画类型
一般来说,动画模型应使用泛型(Generic Animation Type),除了以下例外情况:
·导入角色为人型,且带有由另一个不同层级结构的人型模型播放的动画
·需要用该模型播放不同层级结构的人型模型的动画
·希望使用内置人型功能,例如手臂或腿部IK或目标匹配。
注:人形动画类型不一定是两足类人角色应该选择的正确动画类型。
2.9.4 将动画类型改为人形
在项目窗口中选择本节范例模型MazeLowMan>在检查器中选择Rig标签>将Animation Type改为Humanoid>点击Apply。
2.9.5 映射与人形Avatar的复杂性
泛型骨架与人形骨架的核心区别就在于其Avatars。人形骨架需要Avatar播放动画,泛型骨架则不然。这是因为人形骨架是特例;其变形层级是映射到人形骨骼上的。
在正常情况下,为了使动画可以在多个目标之间共享,每个目标必须具有与动画片段中相同名称的相同层级结构。这是因为变形名称用于构建动画片段的绑定值。如果播放动画片段所依据的层级结构没有具体绑定值,则绑定值将被忽略。这意味着,如果名称不匹配,则动画将无法播放。
当导入的模型是人形时,不再仅使用标准绑定值播放动画片段。取而代之的是,与“人形”定义匹配的动画片段是通过Avatar播放的。
在导入时,来自人形模型的动画片段将从写入变形直接转换为写入肌肉。这被称为肌肉剪辑。在运行时,肌肉剪辑将转换回来写入变形。
由于所有人形都具有这种映射,因此可以通过任何人形模型播放任何人形动画片段。
过程复习
这些转换过程可以总结如下:
导入时:具有变形绑定值的动画片段→人形Avatar→肌肉剪辑
运行时:肌肉剪辑→人形Avatar→设置变形属性
获取用于一个层级的动画片段并通过不同层级播放它的过程称为重定目标(retargeting)。
2.9.6 加载人形Avatar设置
如果Configure...按钮左侧有对勾,那么Unity就可以自动设置Avatar。
选择Configure...按钮后,将立即保存当前场景,这是因为人形Avatar是在独立场景中设置的,所以需要卸载当前场景。
2.9.7 了解映射
加载Avatar设置场景后,检查器将显示Avatar映射。
Avatar设置分为两部分
·映射
·肌肉与设置
映射准确定义了模型的哪些变形与预先定义的人形骨骼的哪些部分相关联。
检查器显示出现在可以分配的骨骼区域。每个点表示一根骨骼。实线表示映射的运行所需要的骨骼。虚线表示可选骨骼。映射的可选骨骼越多,重设目标(retargeting)的质量越高。
使用自动映射
为了更轻松地设置映射,可以通过匹配预期层级和名称试着自动完成映射。
·点击映射标签底部的Mapping下拉菜单,选择Automap。
2.9.8 应用标准动画姿势
变形的位置和旋转在Avatar设置中同样极为重要。它们构成了计算动画的参考姿势。动画片段与肌肉剪辑相互转换时,每个旋转和转换都是与该参考姿势做比较的。Unity使用标准动画姿势作为所有人形动画的目标姿势:T-pose。
·点击映射标签底部的Pose下拉菜单,选择Enforce T-Pose。
2.9.9 设置骨骼
肌肉的定义是骨骼预期在给定轴上旋转(或无法旋转)的范围。
该范围是标准化数值,这意味着该范围为0到1。在导入时,变形旋转将转换为这些标准化旋转范围。然后在运行时将标准化旋转范围转换回变形旋转。
Avatar在导入时的预期运动范围与Avatar在运行时的预期运动范围可能会有所不同。如果是这样,则仍然可能发生转换,因为数据是作为普通骨骼定义上的标准化数值存储的。
但是,这将影响动画中的旋转。
示例
考虑以下示例:
模型的肌肉定义为围绕某条轴的10到90度之间旋转。该模型上的动画需要在某个特定帧上旋转50度。
由于范围已标准化,因此该旋转的数值为围绕该轴旋转范围的0.5。
该动画将重新定位到其他模型。该模型的范围在0到110度之间。来自本动画的0.5旋转值将转换为55。
在编辑器中进行设置
在检查器上方选择Muscles & Settings标签>在Pre-Muscle Settings中打开Head和Neck Nod DownUp菜单>将默认值-40-40改为更大的范围>测试后复位。
2.9.10 创建和应用Avatar蒙版
Avatar蒙版是一种防止动画数据写入其绑定值的方法。人形Avatar和泛型Avatar的运行方式不同,但是总体效果相同:不使用有蒙版源中的变形数据。
人形Avatar的Avatar蒙版
人形Avatar的Avatar蒙版通过使用带有不同可选区域的人形图像来操作。取消选择人形的某个区域即对其加上蒙版。
应用Avatar蒙版
Avatar蒙版可以在两种不同情况下使用:
·在导入过程中导入动画片段时,防止特定变形的动画数据添加到该动画片段中。
·对于动画控制器中的动画图层,防止特定变形的动画数据添加到由此得到的动画控制器所有图层的混合图层中。这些Avatar蒙版必须作为资源创建,但独立于其他Avatar蒙版运行。
您可以在3.7“创建和配置动画图层”中找到关于导入动画片段和动画图层的更多信息。
注意:请记住,Avatar蒙版仅对变形数据加蒙版,这一点很重要。它们不会对同一个游戏物体上的数据当做蒙版变形来加蒙版。
2.9.11 总结
3. 动画器
3.1 动画器组件简介
3.1.1 概述
本节内容
·动画控制器的结构及其与动画器组件的关系。
·动画器组件的不同属性并考虑何时应用哪种属性。
3.1.2 开始之前
3.1.3 了解动画器系统的结构
游戏物体>动画器>动画控制器>动画图层>状态机>状态>动画片段
3.1.4 动画器参数
·浮点(Floats)
·整数(Integers)
·布尔变量(Booleans)
·开关(Triggers)
使用示例
·定义过渡条件
·控制状态属性
·控制混合树(Blend Trees)
3.1.5 动画器组件
动画器组件充当了绑定系统的根(Root)。
绑定系统有两个部分:
·变形路径
·属性名称
变形路径有一个包括以下内容的字符串:
·层级结构中的变形名称,必须遍历该名称才能到达游戏物体。
·有待设置动画的组件和属性。
与动画器组件相同的游戏物体的任何属性都有一条空白路径,因为不需要遍历任何变形即可获取该属性。具有动画器组件的游戏物体的直接子物体上的任何属性都具有该子物体名称的变形路径。这将沿其他游戏物体的层次结构延续。
请务必记住,这种绑定模式意味着只有与动画器组件相同的游戏物体上的属性以及层级中位于其下方的游戏物体属性才能由动画器控制。
3.1.6 动画器组件属性及其用途
在查看动画器系统的结构时,您学习了动画器组件的控制器属性。现在,我们来探讨其他属性。
Avatar设置
除非您为带有人形骨骼的角色设置动画,否则动画器组件的Avatar设置是可选的。此设置定义了动画的变形。
应用根运动
“应用根运动”设置确定是否将对根节点的“位置”或“旋转”进行任何更改。如果启用该选项,则将应用这些更改,允许动画移动根节点。
请记住,根节点不一定是有动画器组件的变形。它可以是使用Avatar的层级上的任何变形。
更新模式
动画器组件的更新模式会影响执行动画器以更新其所控制属性的时间的代码。
当更新模式设置为“正常”时,更新会随渲染系统即时进行(在调用Update和LateUpdate方法之间)。 在大多数情况下,没有理由将其变为“正常”。
当“更新模式”设为“动画物理”时,在调用FixedUpdate方法之后,更新会与物理系统同时进行。当有待设置动画的属性需要与物理引擎互动时(例如,移动Collider时),该设置很有用。
最后一个选项是“无标度时间”(Unscaled Time)。启用此设置后,更新将与渲染系统同步进行,但不受Time.timeScale的影响。这意味着动画的速度不会改变。该设置对于在游戏的其余部分变慢或加速时使UI等对象保持相同速度非常有用。
剔除模式(Culling Mode)
最后一项设置为剔除模式。该设置会影响导致动画器暂停更新以提高效率的因素。
默认选项是“总是播放动画”(Always Animate)。 选择该选项后,将永远不会剔除动画器。
当动画器下所有渲染器的边框超出所有当前渲染的镜头的视锥范围之外,“Cull Update Transforms”选项将停止所有对变形属性的写入。唯一的例外是仍然应用根运动。这可用于并不是总显示在镜头中的动画角色等情况。这将提升性能,因为角色的手脚在大多数情况下不会进行处理,而只是在角色出现时进行处理。
最后一个选项“完全剔除”(Cull Completely)将在动画器下所有渲染器的边框不在所有当前渲染镜头的视锥范围内时,停止所有对所有属性的写入。这应该用于任何带有动画的固定游戏物体。
3.1.7 总结
3.2 动画融合(animation blending)简介
3.2.1 概述
3.2.2 开始之前
3.2.3 什么是动画融合?
当多个动画通过相同的游戏物体层级同时播放时,即为动画融合。
最常见的动画混合是两个或多个动画意欲改变一个绑定值时。结果是,每个动画的值被融合起来,绑定值根据融合值而变化。
3.2.4 动画融合的运行原理是什么?
有几种不同的复杂算法可用于融合动画,其中大多数算法本教程都不会涉及。
但是,您需要知道,所有算法都遵循相同的总体过程:
·每个动画都有权重。该权重表示动画对融合结果的影响程度。
·较高的权重意味着动画的影响更高,而较低的权重意味着动画的影响更低。
·通常,权重是标准化的。这意味着所有待融合动画的权重之和等于1。
动画融合最简单的算法是加权和(Weighted Sum)。它是当前时刻的每个绑定值乘以动画片段的权重。然后,Unity将所有加权值加在一起,并设置结果的绑定值。
示例
动画A在特定时间将灯光组件的强度设置为5。
动画B同时将同一灯光组件的强度设置为10。
动画A的权重为0.2。
动画B的权重为0.8。
这两个动画的融合导致灯光组件的强度为:
5 * 0.2 + 10 * 0.8 = 9
3.2.5 哪些功能使用动画融合?
使用动画融合的三个最常见的功能是:
·转场
·混合树
·图层
让我们来逐一详细探讨。
转场
动画融合最常出现在转场中。 当转场开始时,第二个状态的动画开始播放。随着转场继续,第二个状态的权重增加,前一个状态的权重降低。
融合树
融合树用于代替状态中的单个动画片段。它们融合了包含的多个动画片段。
图层
图层融合的运作方式与转场和融合树的运作方式略有不同。在将图层中的所有动画与下一个图层融合之前,需要对其进行完整评估。然后在与后续图层融合之前,评估该融合的结果,依此类推。
3.2.6 动画融合实践
这些功能可以单独使用,但并不总是那么简单。例如,两个混合树之间的转场如何做?
答案是动画融合可以嵌套(nested)。加权是相乘得到的,因此每个动画片段都会在计算最终结果之前先计算其权重。
使用动画功能时要记住的最重要的事情之一是,虽然它们全部用于播放和融合动画,但是每个功能的作用方式都不相同。获得良好动画效果的关键是了解应使用哪些工具来融合动画以获得所需的结果。
3.2.7 总结
3.3 创建并设置动画器状态
3.3.1 概述
每个动画状态都包含一个动作。动作要么是动画片段,要么是通过混合树融合的动画片段集合。播放动画状态的同时,也会播放其中的动作。
动画状态是状态机的核心组成部分之一,状态机又是动画控制器的核心组成部分之一。
3.3.2 开始之前
3.3.3 创建动画器状态
有两种创建动画器状态的方法:
·将动画片段资源从项目窗口拖进动画器窗口。
·右键单击动画器窗口,选择Create State>Empty。
选择的方法基于你希望动画器状态包含的动作。
3.3.4 通过动画片段创建新的动画状态
Window>Animation>Animator>选择游戏物体MazeLowMan>在项目窗口中,选择本节资源中的AnimationClips>展开模型HumanoidRun,找到动画片段Run>将Run从项目窗口拖入动画控制器窗口,创建新的动画状态并命名为Run。
3.3.5 基本动画状态设置:名称与标签
动画状态的名称和标签单纯是用来识别的。名称必须是独一无二的,但标签不用。
3.3.6 状态播放控制设置:动作、速度与倍数
动作(Motion):该项可以设为动画片段,也可以设为融合树。
速度与倍数(Multiplier):不同的速度值可以产生慢放或快放效果。如果将这里的值作为默认值,并启用倍数,那么最终的播放速度将为速度值乘以动画器参数。
3.3.7 调整动画速度
启用Multiplier右侧的Parameter>调整Speed参数(1-4)>点击Play观察效果
3.3.8 动画状态播放控制设置:标准化时间
另一种控制动画状态播放的方法是直接控制其标准化时间。
标准化时间是用0-1的数值衡量当前运动时间的概念。
·当标准化时间为0时,动画状态处于起点。
·当标准化时间为0.5时,动画状态处于中点。
·当标准化时间为1时,动画状态处于终点。
你可以用动画参数的值作为动画状态的标准化时间,设定动画状态运动过程中每帧的值。
动画器窗口>启用Motion Time的Parameter>选择希望使用的动画参数。
3.3.9 动画状态播放控制设置:循环偏离(Cycle Offset)
该设置与标准化时间并用,它设定了状态开始播放的标准化时间。如果你希望改变这个设置,可以将其设为浮点或者令其由浮点参数控制。
3.3.10 人形设置
人形状态的两个额外设置
·镜像:将动画左右翻转。
·足部IK:使用肌肉剪辑数据估计哪只脚应该踩在地上。使用足部IK时,足部的位置是锁定的。该功能在以下情况很有用:(1)动画片段压缩导致足部在空闲(idle)动画中移动。(2)融合两段动画导致足部在应该固定的时候轻微滑动。
注:该设置是基于估计值,不能确保适用于所有动画数据。
3.3.11 其他设置
写入默认值(Write Defaults)
要了解其工作原理,首先需要了解Animator System处理其动画绑定的方式:
·动画器从其包含的所有动画片段中收集所有绑定值,并在每帧中写入每个绑定值。
·如果动画状态的动作未写入特定的绑定值,则动作取决于“写入默认值”设置。
·如果启用“写入默认值”,则写入绑定的默认值。如果禁用该选项,则不写入绑定值,而是保持原值。
转场列表(List of Transitions)
该列表是转场的优先顺序。
3.3.12 总结
3.4 创建和设置融合树
3.4.1 概述
融合树是同时播放多个动画片段的一种方法。
3.4.2 开始之前
3.4.3 融合树基础
融合树与动作
每个动画状态都播放一个动作。动作可以指动画片段,也可以指融合树。融合树播放的是一组动作。
融合树与标准化时间
融合树使用动画片段的标准化时间,从而同步类似的动画片段。
3.4.4 融合树类型
·1D
·2D简单方向
·2D自由方向
·2D自由笛卡尔
·直接
它们的区别仅在于如何计算融合树中动画片段的权重。
动作阈值
阈值是动作处于最大权重的那一点。1D融合树有一个浮点阈值。2D融合树有两个浮点值,Pos X和Pos Y。
直接融合树没有阈值,而是直接设定有具体参数的动作权重。
动画参数与维度
每个融合树都有一个或多个动画参数。这些参数的值与动作阈值的接近程度决定了每个动画片段在结果中的权重。
融合树的维度显示了它使用了多少动画参数:
·1D融合树使用一个浮点参数,其值被称为blend value。
·2D融合树使用两个浮点参数。它们的值定义了blend position。
·直接融合树是一种特殊类型,它使用任意指定的浮点参数。
3.4.5 1D融合树
根据动作阈值与融合值的距离决定权重,距离越近权重越大。
例如,如果有两个阈值分别为1和2的动作,融合值为1.7,那么
·阈值为1的动作的权重为0.3
·阈值为2的动作的权重为0.7
3.4.6 创建1D融合树
在项目窗口中,打开1DBlendTrees场景>选择MaxeLowMan>找到Animator>在Controller属性中双击WalkRunBlending Animator Controller,打开动画器窗口>右键单击背景,选择Create State>From New Blend Tree>双击新创建的动画状态>选择新的Blend Tree,检查其设置。
3.4.7 了解并设置融合树
名称
融合树的名称必须有别于包含融合树的动画状态的名称。
融合类型
融合值参数
·一维融合树的参数为Blend Value
·二维融合树的参数为blend position
·直接融合树:每个动作对应一个参数。
3.4.8 了解融合图
一维融合树

拖动曲线可以改变动作阈值,但不建议这样做,因为这种方式无法精确控制阈值。
二维融合树

直接融合树
直接融合树没有图形,因为每个动作的权重完全独立。
预览动画
一维融合树和二维融合树:拖动红点即可预览动画
直接融合树:通过滑块改变参数的权重值
3.4.9 在一维融合树中添加动作
在检查器中点击Add(+),选择Add Motion Field>重复上述步骤>在项目窗口中找到AnimationClips>展开HumanoidWalk和HumanoidRun>将Walk和Run动画片段拖入Motion,确保Walk阈值为0,Run阈值为1
时间尺度设置:时间尺度的运行原理和动画状态速度类似,除了它仅适用于特定动作。
如果动作为人形动画,也可以对动画进行镜像操作。
嵌套融合树(Nesting Blend Trees):如果希望在这个融合树中嵌套另一个融合树,可以选择Add(+)>New Blend Tree。
3.4.10 检测融合树
在层级窗口中选择MazeLowMan>点击Play>在检查器中,用Speed滑块调整走与跑的动画>再次点击Play。
3.4.11 二维融合树:简单方向
当每个融合位置轴上只有两个动画时,应该使用二维简单方向融合树。例如,如果坐标轴四方向中每个方向都有一个不同的行走动画时,就应该使用二维简单方向融合树。阈值标签为Pos X和Pos Y。
使用这类融合树时,也可以在中心融合位置(0,0)有一个动作,表示无方向或中性方向(可选但推荐)。此时,输出权重取决于两个线性插值的结合:
(1)样本点两个方向之间的插值,取决于从中心点到样本点的角度。
(2)最终动作与中心动作之间的插值,取决于距中心的距离。样本点距中心越近,分配的权重越高。
3.4.12 二维融合树:自由方向
二维自由方向融合树允许每个方向有多个动画。
使用的插值算法被称为极性梯度带插值(Polar Gradient Band Interpolation)。
3.4.13 二维融合树:自由坐标系
当动作不代表不同方向时,应该使用二维自由坐标系融合树。这是因为在自由坐标系中,X和Y可以代表不同概念。最终权重不是基于角度,对中心点也没有特别对待。
二维自由坐标系融合树可以用于与一维融合树类似的情况,其中每个动作也是一个一维融合树。区别在于,二维自由坐标系融合树使用更复杂的插值算法,即笛卡尔梯度带插值(Cartesian Gradient Band Interpolation)。这意味着你可以在参数空间内更自由地使用动作。
3.4.14 测试二维自由坐标系融合树
建立二维自由坐标系融合树的过程和建立一维融合树类似,但需要设置更多阈值。
在项目窗口中打开2DFreefromCartesianBlendTrees场景>在层级窗口中选择游戏物体MazeLowMan>点击Play>在检查器中找到Speed Turn Control脚本,调整两个参数,观察其对角色的影响>再次点击Play,退出播放模式。
3.4.15 复习二维自由坐标系融合树的设置
在检查器中找到Animator>在Controller属性中双击WalkRunTurnBlending Animator Controller>双击Locomotion状态>选择LocomotionBlendTree,观察其设置。
3.4.16 直接融合树
直接融合树最简单,但最不常用。它允许有任意数量的动作,每个动作的权重直接由动画参数控制。它没有阈值设置,而代之以参数选择。这意味着你可能有多个权重为1的动作。
您应该将直接融合树用于融合形状动画之类的动画,其中每个融合形状都是独立的。融合形状通常用于面部动画等。例如,您可能有一个融合形状表示微笑,而另一个融合形状表示皱眉。将它们作为单独的动作可让您独立控制微笑和皱眉。
3.4.17 融合树的自动设置选项
对于包含带根运动的动作的一维融合树和二维融合树,动作列表下方有自动选项。它们可以自动计算一维融合树的阈值和二维融合树的位置。
这些设置可以根据根运动将运动阈值设置为特定值。设置阈值后,你可以随时更改它们。
可以用于设置阈值的根运动有:
速度:动画每秒移动的平均米数。
速度X:动画每秒在本地X轴上移动的平均米数。
速度Y:动画每秒在本地Y轴上移动的平均米数。
速度Z:动画每秒在本地Z轴上移动的平均米数。
角速度:动画每秒绕本地Y轴的平均旋转速度。可以弧度或度为单位进行计算。
选择选项
最佳选择取决于您要融合的动画。
例如:
·如果您想将各种左移/右移动画与行走和奔跑动画融合,那么使用速度X和速度Z可能是不错的选择。这是因为这些动画的属性不同。
·如果要混合各种旋转动画,那么角速度可能是正确的选择。
这些选项非常有用,因为它们允许根据动画的物理特性使用参数设置融合值或融合位置。
如果您有一个速度参数和一个带有基于速度的动作的融合树,则只需将速度参数的值设置为您希望角色移动的速度,即可获得所需的结果(假设融合树具有适应该速度的动画)。
调整时间尺度
如果融合树中的所有动作都不是子融合树,则将显示调整时间尺度的选项。
与“计算阈值/位置”一样,这些设置使您可以设置时间尺度的值(可以随时调整)。但是,与计算阈值/位置不同,调整时间尺度将改变运动的速度,而不是运动的阈值。
要通过时间尺度设置来设置动画速度,您有两个选择:
(1)同质速度:设置所有速度,使带有非零根运动速度的动画具有相同速度。这样会考虑到空闲动作之类的动画,并且不会改变它们的速度。
(2)重置时间尺度:将所有速度设置回1。
3.4.18 总结
3.5 创建并设置过渡
3.5.1 概述
过渡(Transitions)是一种控制动画回放和融合的方法。
3.5.2 开始之前
3.5.3 当前状态和下一个状态
当前状态和下一个状态的权重将以线性方式此消彼长。
3.5.4 创建过渡
在动画器窗口中,右键单击EllenRunForward状态,选择Make Transition>左键单击EllenQuickTurnLeft>选择过渡线>在检查器中展开设置菜单。
注:如果两个动画之间设置了多个过渡条件,那么过渡线上的箭头将变为三个。
3.5.5 调整退出时间设置
使用条件(Conditions)和退出时间(Exit Time)可以控制过渡发生的时间。
只有满足以下两条标准时才会开始过渡:
(1)前一帧的标准化时间小于退出时间;
(2)当前帧的标准化时间大于退出时间。
3.5.6 调整过渡持续时间设置
过渡持续时间可以用秒衡量(启用Fixed Duration),也可以用当前状态的标准化时间衡量(禁用Fixed Duration)。
刚才已经设置过渡开始时间为第一个动画开始后81%,那么过渡持续时间应为EllenRunForward长度的19%。
在检查器窗口中,禁用Fixed Duration>将Transition Duration设为0.19。
3.5.7 测试过渡
3.5.8 了解过渡偏离(Transition offset)
偏离是发生过渡时下一个状态开始播放的标准化时间。它可以用于在过渡开始时保持动画同相(in phase)等,例如在角色动画中,确保腿部位置类似。
3.5.9 了解过渡中断设置
过渡可以被其他过渡打断。这时,过渡当前帧的动画值将被存储起来,并作为中断过渡的当前状态。这意味着中断过渡的融合发生在初始过渡的某个时点和中断过渡的下一个状态之间。
“中断来源(Interruption)”和“有序中断(Ordered Interruption)”设置控制如何通过另一个过渡来中断过渡。
中断来源
动画控制器带有过渡列表,当前可以被每个动画图层采用。每帧中都会检查这些过渡的条件和退出时间。默认情况下,此列表仅包含当前状态的过渡列表之后的状态的过渡。
但是,当动画层正在过渡时,该过渡列表将替换为来自任何状态的过渡,并且由当前过渡的中断来源定义其他过渡。
每个中断来源的其他过渡是:
·无:没有过渡添加到列表中。
·当前状态:将当前状态的有序列表中的过渡添加到列表中。
·下一个状态:将下一个状态的有序列表中的过渡添加到列表中。
·从当前状态到下一个状态:将当前状态和下一个状态的有序列表的过渡都按该顺序添加到列表中。
·从下一个状态到当前状态:将下一个状态到当前状态的有序列表的过渡都按该顺序添加到列表中。
有序中断
有序中断控制当前状态的低优先级过渡是否可以中断过渡。如果启用该属性,则由于当前状态的低优先级过渡顺序较低,因此它们不能中断过渡。
3.5.10 了解过渡条件
过渡条件是对动画参数值的逻辑描述,满足这些条件时将启动过渡。每个过渡可以有多个条件,全部满足时才开始过渡。
每类参数都有不同的条件逻辑描述:浮点参数、整数参数、开关参数和布尔变量。
创建条件:在条件列表底部点击New Condition(+)>选择条件所基于的参数>如果参数是浮点或整数,选择比较类型>如果参数是浮点、整数或布尔变量,选择与参数进行比较的值。
3.5.11 任意状态
动画控制器的每一层都有一个特殊节点,称为“任意状态(Any State)”。它允许从其创建过渡,但不允许过渡指向它。从任意状态发起的过渡总在列表首位。只有在确定每帧都要检查任意状态时,才应该使用任意状态。
3.5.12 总结
3.6 创建状态机
3.6.1 概述
状态机是动画控制器的核心结构之一。
3.6.2 开始之前
3.6.3 状态机介绍
每个动画控制器都有一个或多个动画图层,每个动画图层包含一个状态机。每个状态机中可能有更多的嵌套状态机。
3.6.4 创建状态机
状态机是一种组织工具,将状态和过渡组织起来。除非有很多状态要组织,否则可能不创建状态机更有效率。
右键单击动画控制器背景,并选择Create Sub-State Machine>双击新创建的子状态机并打开>双击(Up)node,返回母状态机。
在状态机中添加状态的两种主要方法:
(1)双击状态机打开并创建状态
(2)如果已经创建了状态,可以点击状态并将其拖拽至状态机节点,从而将其添加到状态机中。
3.6.5 了解状态机的过渡
过渡的两种方法:
·从状态直接过渡
·从状态过渡到状态机,再从状态机过渡
3.6.6 了解状态机的节点
建立状态机时,可以使用上节点(Up node)或进入和退出节点(Entry and Exit nodes):
·从状态或状态机发出的过渡
·从嵌套在其他状态机内部的状态机发出的过渡
上节点表示内外节点之间的直接过渡。
进入和退出节点用于状态机本身的过渡。它必须与一个或多个状态机本身的过渡相结合。
使用进入与退出节点的过渡
过渡是以下要素的结合:
·逻辑,它决定了过渡发生的时间
·融合,它决定了当前状态和下一个状态如何融合
使用状态机(而非状态)过渡时,逻辑和融合将分为多个过渡。一些过渡单纯负责逻辑,另一些过渡同时负责逻辑和融合。
3.6.7 总结
3.7 创建和设置动画图层
3.7.1 概述
动画图层是动画控制器结构的一部分,也是另一种同时播放和融合多个动画的方式。
3.7.2 开始之前
3.7.3 动画图层基础
两种方式
(1)融合优先于其他动画图层的动作。
(2)融合添加到其他动画图层的动作中。
动画图层索引:动画图层有索引。基础图层的索引序号为0。动画图层按升序评估(从0开始)。
动画图层权重:每个动画图层都有权重,但动画图层之间的融合与过渡或融合树略有不同。
3.7.4 遮罩
需要拗动作时,可以通过遮罩使不同部分的骨骼播放独立动作。方法是在需要只播放部分动画的动画图层中加入对Avatar Mask资源的引用。
3.7.5 动画图层融合过程
动画图层按照索引序号升序评估动画结果:先评估图层0>评估图层1,再与图层0融合>评估图层2,然后与图层0和图层1的融合结果融合>以此类推
两种融合方式:优先融合(Override blending)和叠加融合(Additive blending)
3.7.6 优先融合
优先融合类似于使用过渡和一维融合树的融合。随着下一个动画图层的贡献增加,前一个动画图层的贡献减少。
3.7.7 叠加融合
叠加融合用于支持叠加动画。叠加动画是动画数据本身作为与参考姿势的变化而存储的动画。
使用叠加融合时,已评估动画图层的实际权重总为1。叠加图层的动画被加到这些图层的贡献上。所取的动画数据是默认值和当前值之间的变化值,用来计算加权贡献。
3.7.8 探索叠加动画
在层级窗口中选择Ellen>点击Play>在检查器中找到Layer Weight Setter组件>调整Weight并观察效果>点击Play退出
3.7.9 了解动画图层的设置
在层级窗口中选择Ellen>打开动画器窗口>选择左上的Layers标签,可以看到有两个图层:基础图层(索引序号为0)、AdditiveHeavyBreathing图层(索引序号为1)
选择AdditiveHeavyBreathing图层>打开设置齿轮
3.7.10 了解权重、Avatar遮罩和融合设置
权重:增加权重将增加本图层对最终动画的贡献
Avatar遮罩:用于防止动画图层写入身体的特定部分。
融合:可以设为优先融合或附加融合。
3.7.11 了解同步(Sync)与IK Pass
同步
启用同步后,将需要确定你想与当前动画图层同步的动画图层。这将创建与源动画图层相同的状态机。
默认情况下,状态机将匹配源状态机的时间。这意味着当源动画图层发生过渡时,同步动画图层夜间该发生过渡。
但是,如果启用Timing,则状态持续时间将是源动画图层的动画片段长度和同步的动画图层的动画片段长度的内插值。它们将基于同步的动画图层的权重。
查看启用Timing的同步示例
例如,假设您有一个带有“行走”和“奔跑”状态的基本动画图层。然后,您创建另一个称为“受伤”的图层,该图层被同步到基本图层。
受伤图层将具有设置了相同过渡的行走和奔跑状态,但是你可以将动画片段替换为“受伤行走”和“受伤奔跑”。由于图层已同步,因此它们将一起过渡。但是,它们具有不同的持续时间。
如果启用了Timing,则“受伤图层”上的状态持续时间将向基本图层上的状态持续时间进行内插。受伤图层的权重为1表示状态将与基础图层上的状态具有相同的持续时间。
IK Pass
最后一个设置是IK Pass。此设置仅适用于人形动画。
如果启用,它将导致在与动画器组件所挂的游戏物体上的MonoBehaviours调用评估IK的方法,以及该动画图层的状态机行为。
3.7.12 总结
4. 动画脚本简介
4.1 一般动画脚本简介
4.1.1 概述
4.1.2 开始之前
4.1.3 控制动画参数的值
动画参数可以控制动画的运行方式,例如:
·何时开始过渡
·融合树的融合值与融合位置
·各种状态设置
4.1.4 设置动画参数的值
控制动画参数的值的四种方法:
·animator.SetBool()
·animator.SetFloat()
·animator.SetInteger()
·animator.SetTrigger()
每种方法都必须定义变量名称和变量的值。
定义变量名称的两种方式:使用名称字符串;使用被称为哈希数(hash)的整数表示名称
例如:animator.SetFloat("Speed", 5f);
或
animator.SetFloat(speedParameterHash, 5f);
字符串哈希值
speedParameterHash为速度参数名称的哈希数。
为了在动画控制器中创建字符串的哈希数,可以使用以下静态方法:
Animator.StringToHash()
然后可以用它初始化子变量:
int speedParameterHash = Animator.StringToHash("Speed");
为了防止误操作被更改,可以将其设为只读:
static readonly int speedParameterHash = Animator.StringToHash("Speed");
一个完整例子:
4.1.5 获取动画参数的值
获取动画参数值的方法:
·animator.GetBool()
·animator.GetFloat()
·animator.GetInteger()
调用布尔参数值的示例:
bool isCharacterGrounded = animator.GetBool("IsGrounded");
或
bool isCharacterGrounded = animator.GetBool(isGroundedParameterHash);
如果导入动画使用了附加动画曲线,且曲线的值和动画参数的浮点值相同,那么在评估动画时,参数的值将被设为动画曲线的值。
4.1.6 控制动画图层的权重
设置动画图层权重的两种方法:
·animator.SetLayerWeight()
·animator.GetLayerWeight()
示例
animator.SetLayerWeight (1, 0.5f);
或
float shootingLayerWeight = animator.GetLayerWeight (2);
4.1.7 动画流控制(flow control)简介
需要独立控制动画流时,可以使用以下方法:
·Play()
·PlayInFixedTime()
·CrossFade()
·CrossFadeInFixedTime()
4.1.8 使用Play和PlayInFixedTime
这两种方法都有最多三个参数:
·需要播放的状态名称(字符串或状态名称的哈希数)
·需要播放的状态所在图层的索引
·状态开始播放的时间
Play()的时间参数是标准化的(0-1),PlayInFixedTime()的时间参数以秒为单位。
示例
animator.Play(“Run”, 0, 0.1f);
或
animator.PlayInFixedTime(shootStateHash, 1, 0f);
4.1.9 使用CrossFade和CrossFadeInFixedTime
这两种过渡方法最多有五个参数:
·过渡目标名称(字符串或状态名称的哈希数)
·淡出时长
·交叉淡出(cross-faded)的目标状态图层索引
·与过渡目标状态的偏离
·同时淡出淡入到开始的时间
CrossFade使用标准化时间,CrossFadeInFixedTime使用秒数。但两种方法的最后一个参数均使用秒数。
4.1.10 动画流控制示例
animator.CrossFade(walkStateHash, 1f, 0, 0.1f, 0f);
该同时淡出淡入效果与同时淡出淡入源状态的时长相同,因为标准化过渡时长参数为1。过渡状态位于基础动画图层(0)上。当同时淡出淡入开始时,将发生三件事:
(1)淡出状态将在常规过渡开始时同步播放。
(2)淡入状态将在1/10处开始播放,因为时间偏离参数为0.1f。
(3)它将播放整个过渡,因为它开始的标准化时间为0f。
示例
4.1.11 MonoBehaviour信息
多数动画脚本可以在MonoBehaviour的Update或FixedUpdate中调用,但有些动作是例外,尤其是MonoBehaviours:OnAnimatorMove和OnAnimatorIK。
OnAnimatorIK
只有当动画组件有人形Avatar时调用OnAnimatorIK。它可以用于任何IK。
OnAnimatorMove
该方法可以在人形动画或泛型动画中调用。通常,动画组件中的根运动可以启用或禁用,但如果MonoBehaviour调用了该方法,则它将控制根运动。
用animator.deltaPosition和animator.deltaRotation属性可以改变动画行为。
调用顺序
这些信息按照动画控制器的内部更新过程的顺序调用。该变化基于动画组件中的Update Mode设置。
如果Update Mode设为Normal,那么调用顺序为Update>OnAnimatorMove>OnAnimatorIK>LateUpdate
如果Update Mode设为Animate Physics,那么调用顺序为FixedUpdate>OnAnimatorMove>物理系统运行内部更新,检查碰撞,并解决它们>OnAnimatorIK
4.1.12 状态与动画片段信息
用于了解动画控制器情况的部分方法:
是否在进行过渡?
animator.IsInTransition()
整数值代表希望检查的动画图层索引,如果正在进行过渡则返回值为真。
播放的是什么状态?
animator.GetCurrentAnimatorStateInfo()
animator.GetNextAnimatorStateInfo()
整数值代表希望检查的动画图层索引,返回结果为AnimatorStateInfo。它包括关于状态的精确信息,例如:
·长度(Length)
·名称和标签的哈希数
·速度
如果下一个状态没有动画图层过渡,将得到默认值。
获得关于动画片段的信息
animator.GetCurrentAnimatorClipInfo()
animator.GetNextAnimatorClipInfo()
它的运行原理类似于用来获取AnimatorStateInfor的方法,但返回的是AnimatorClipInfors,它将给出播放的动画片段及其权重(同时考虑融合树和过渡的融合权重)。它不考虑动画图层的权重。
4.1.3 总结
4.2 人形动画脚本简介
4.2.1 概述
人形骨架有可预测的结构,且在Unity设置变形值之前,动画被转换为“肌肉空间(muscle space)”。这意味着可能内置有IK和目标匹配等特征。
4.2.2 开始之前
4.2.3 目标匹配与IK基础
在正常情况下,变形层级按照正向运动学(Forward Kinematics, FK)运行。
有时我们希望单独设置层级底部(称为effector)骨骼的位置或旋转。这时,层级其余部分需要变化以适应effector的位置或旋转。我们可以通过两种方式来实现这种效果:
(1)目标匹配
(2)反向运动学(IK)
4.2.4 目标匹配简介
目标匹配移动层级的根,使操纵器(effector)处于正确位置或旋转,而不用改变其余层级。
4.2.5 反向运动学简介
IK不移动层级的根,而是改变角色的姿势。
用于人形骨架时,IK使用两根骨骼代表手臂或腿。
4.2.6 目标匹配
目标匹配使用MatchTarget方法或动画控制器。该方法将在你希望目标匹配开始前的任意时间在状态中被调用。
MatchTarget的参数可以分为三组,每组有两个参数:
(1)关于被匹配目标的信息
(2)关于被匹配操纵器的信息
(3)关于目标匹配何时开始的信息
目标信息参数是被匹配的世界空间位置和被匹配的世界空间旋转。
AvatarTarget
操纵器的第一个信息参数是决定哪部分身体是操纵器的枚举。它被称为AvatarTarget,因为它被用于决定哪部分人形Avatar将被匹配给具有以下值的目标:
·根
·身体
·左脚
·右脚
·左手
·右手
根通常位于两脚之间,身体为角色重心。
MatchTargetWeightMask
它决定了初始位置与操纵器操纵的目标位置的平衡。它有两个部分:
·位置权重
·旋转权重
位置权重(称为positionXYZWeight)是一个三维向量,每个轴的值在0和1之间。
旋转权重(称为rotationWeight)是允许在初始旋转和目标旋转之间进行插值的浮点。
最后两个参数为赋予状态标准化时间的浮点。它们表示目标匹配的开始时间和到达目标的时间。
4.2.7 了解目标匹配案例
在项目窗口中打开示例场景>选择游戏物体MazeLowMan>在检查器中,禁用Vault Target Matching脚本>播放并观察,看到人物的手并没有接触到障碍物,且腿部穿过了障碍物>退出播放状态,并重新启用Vault Target Matching脚本>播放并观察。
4.2.8 人形反向运动学
与动画使用的双骨骼反向运动学(IK)一起使用的有三个重要变量:
(1)目标位置
(2)目标旋转
(3)暗示位置
目标位置和目标旋转是手或脚试图达到的位置和旋转。暗示位置是肘部和膝盖试图达到的位置。
4.2.9 了解IK方法
以下三个重要变量都有自身的权重,可以用于手臂或腿。动画控制器有一种方法可以设置每个变量及其权重,因此共有六种方法。
·SetIKHintPosition
·SetIKHintPositionWeight
·SetIKPosition
·SetIKPositionWeight
·SetIKRotation
·SetIKRotationWeight
所有方法都有两个参数:影响的身体部分;设置的值
使用OnAnimatorIK方法
这些方法可以在动画的IK pass中调用。为此,需要使用MonoBehaviour的OnAnimatorIK方法。
OnAnimatorIK的运行原理非常类似于MonoBehaviours中的Update。它发生在Update或FixedUpdate之后(取决于动画器的更新模式)。
在每个启用IK Pass的动画图层,每次更新将调用一次OnAnimatorIK。每次调用将图层索引作为参数传输。这意味着你可以分别处理不同的IK用途。
4.2.10 总结