# 对 Unity 动画系统 Mecanim 的调研

有一个对 Mecanim 进行介绍的 很好 的一个视频 → http://www.58kaifa.com/course/24,在看完这个视频根据 Unity 圣典进行了下文整理时, 让我理解更加深刻,以后实践时会更加得心应手。

Unity 有一个丰富并且精密的动画系统叫做 Mecanim。

1. 相关术语整理 #

Animation Clip 相关

  • Animation Clip 动画剪辑:可以用于角色或者简单动画的动画数据。它是动作的简单“单元”,诸如(特别的实例)”Idle” 空闲、”Walk” 走路、”Run” 跑步、等等;
  • Body Mask 身体蒙版:一个用于包括或排除身体部位骨骼的规格;[Asset (.mask),在动画分层和导入器中使用];
  • Animation Curves 动画曲线:曲线可以附加到各种动画剪辑并且被游戏中的各种参数来控制;

Avatar 相关

  • Avatar 阿凡达:从一个骨架重定向到另外一个骨架的界面;
  • Retargeting 重定向:把为一个模型创建的动画应用到另外一个模型;[在外部工具中完成,比如 Max 或者 Maya]
  • Skinning 蒙皮:把骨骼关节绑定到角色网格或者“皮肤”的过程;[在外部工具中完成,比如 Max 或者 Maya]
  • Muscle Definition 肌肉定义:一个 Mecanim 概念,它允许你更直觉化地控制 Avatar。当一个 Avatar 准备好了之后,Mecanim 工作在肌肉空间,这比骨骼空间更直觉化;
  • T-pose T 字姿势:角色双臂平身形成一个“T”字的姿势。角色必须保持这个姿势来制作 Avatar;
  • Bind-pose 绑定姿势:角色在建模过程中的姿势;
  • Human template 人形模板:一个预先定义的骨骼映射;[Asset (.ht),用于从 FBX 文件中匹配骨骼到 Avatar]

Animator and Animator Controller 相关

  • Animator Component 动画组件:在模型上使用 Mecanim 动画系统的组件。这个组件引用一个控制动画的 Animator Controller 资源;
  • Root Motion 根动作:角色根级的动作,它可以被动画本身或者外部控制;
  • Animator Controller (Asset) 动画控制器(资源):动画控制器通过动画层中的动画状态机,还有被参数控制的混合树来控制动画。同一个 Animator Controller 可以被多个模型使用 Animator 组件引用;[Asset (.controller)]
  • Animator Controller (Window) 动画控制器(窗口):动画控制器在其中被可视化并编辑的窗口;
  • Animation Layer 动画层:每个动画层包含一个控制整个模型或者部分模型的动画状态机。例如全身层可控制走路、跳跃并且更高的层面控制上半身动作比如投掷、跳跃。更高层对于身体部位有更高的控制权;
  • Animation State Machine 动画状态机:一个控制动画状态之间交互的图。每个状态引用一个混合树或者单一动画剪辑;
  • Animation Blend Tree 动画混合树:基于浮点动画参数,用于连续在多个近似的动画剪辑之间进行混合;
  • Animation Parameters 动画参数:用于在脚本和 Animator Controller 之间通信。一些参数可以在脚本中设定并且在控制器中被引用,另外一些参数是基于在动画剪辑中的自定义曲线并且可以使用脚本 API 来采样;
  • Inverse Kinematics (IK) 反向动力学:基于世界中各种对象来控制角色身体部分的能力;
  • Animation Component 动画组件:使用非 Mecanim 动画时需要的组件;

2. Mecanim 提供的功能 #

Mecanim 提供了:

  • 用于人类角色设计的简单工作流;
  • 动画重定向 – 能够把一个动画应用到多个不同模型的能力;
  • 用于对齐影片剪辑的简化的工作流;
  • 方便的影片剪辑预览,变换和交互。这使得动画师的工作可以更多地独立于程序员,方便在游戏逻辑代码挂接之前建立原型和预览;
  • 使用一个可视化编程工具来管理动画之间复杂的交互;
  • 对身体不同的地方使用不同的逻辑进行动画控制;

3. Mecanim 工作的流程 #

Mecanim 的工作流可以被分割为如下 3 个主要的阶段:

  1. 资源预备和导入。这是由美工或者动画师完成的工作,使用第三方的工具,比如 3D Max 或者 Maya。这一步独立于 Mecanim 的特性;
  2. 为 Mecanim 设定角色,有 2 种途径:(1)类人角色配置。Mecanim 对于类人角色有一个特别的工作流,使用扩展后的 GUI 和重定向。配置包含创建和设定一个 Avatar 并且调整肌肉定义。(2)通用角色配置。这是为任何东西像是人、有动画的柱子、四足动物之类设计的。重定向在这里是不支持的,但是你仍然可以得到后文中描述的 Mecanim 的好处。
  3. 让角色动起来。这包括设定动画剪辑和它们之间的交互,还包括状态机和混合树,列出动画参数,还有从代码中控制动画;

4. 资源准备和导入 #

4.1. 类人网格 Humanoid Meshes ##

为了应用 Mecanim 的类人动画系统和重定向的所有好处,你需要有一个绑骨并蒙皮的类人网格。

  1. 一个角色模型通常是由 3D 包组成或者从一个导出前更加复杂的网格类型转换为多边形或者三角网格;
  2. 一个定义了一组网格内的骨骼和他们的之间的运动关系的关节体系或者骨架,必须是为了控制角色的运动而创建的。众所周知创建这样关节体系的过程称作搭骨架(rigging);
  3. 一个网格或者皮肤必须被链接到关节体系来定义这个给定关节被动画化时角色的某一部分网格如随之运动。这个链接骨架和网格的过程就是蒙皮;

PS 蒙皮网格 - 建模后,模型就会有纹理并且已三角化

总结:预备角色的步骤 →

建模 -> 搭骨架 -> 蒙皮

Modelling 建模 ###

这是在 3D 建模工具包 - 3DSMax,Maya,Blender,诸如此类来建立你自己的类人网格的过程。尽管这是一个属于它们(建模工具)自己的主题,这里有一些你可以遵循的指导原则来保证一个模型可以很好的在 Unity 的动画系统中使用。

  • 遵循合理的拓扑结构。一个“合理” 的网格结构的精确意义是非常微妙的,不过通常情况下,你应该牢记模型的顶点和三角面在动画化之后会怎样变形。一个不好的拓扑结构会让网格变形地非常难看。你可以从已有的 3D 角色网格学习很多拓扑结构是如何安排的以及这样安排的原因。
  • 注意网格的缩放比例。做一次导入测试,比较导入的模型和一个“米立方”(大多情况下是一个边长 1 米的 Unity 标准立方体元素)。检测你的 3D 建模工具包使用的单位并且调整导出设定使得模型的尺寸处在相对这个立方体合适的比例。你必须小心,很容易创建出没有任何标注的缩放比例的模型并且最终会造成一些导入进 Unity 之后不成比例的物体。
  • 安放角色使得角色的脚站在坐标原点或者模型的“锚点”。角色通常是竖直地走在地面上,如果角色的锚点(也就是他的变换中心)在地面上会更容易控制。
  • 如果你会的话,使用 T 字姿态建模。这会对在三维空间中细化化多边形细节(比如,腋下)有帮助。这也会使得放置骨架到网格中更容易。
  • 清理你的模型。只要可能的话,覆盖孔洞,焊接顶点并且移除隐藏的面,这会对蒙皮有帮助,特别是自动蒙皮过程。

Rigging 搭骨架 ###

这是创建骨架上的关节来控制你的模型进行运动的过程。3D 建模工具包提供了各种方法为类人骨架创建关节。从已经构建好的可以缩放后放入网格的两足动物骨架,到创建特别骨骼的工具还有父子化骨骼结构。尽管这方面的细节超出了 Unity 的范围,这里还是有一些通用的准则:

  • 学习已有的类人骨架体系(比如,两足动物)并且在可能的地方尽量模仿这样的骨骼架构;
  • 确保臀部是整个骨架的根节点;
  • 在骨架中至少要有 15 个骨骼;
  • 角色的关节点/骨骼结构应该按照自然的结构建立。手臂和腿成对出现,你应该对骨骼使用一致的命名(比如“arm_L”命名左臂”“arm_R”命名右臂,诸如此类)。一个体系结构可能包含:(1)HIPS - spine - chest - shoulders - arm - forearm - hand 即,臀部 - 脊椎 - 胸部 - 肩膀 - 手臂 - 前臂 - 手 (2)HIPS - spine - chest - neck - head 即,臀部 - 脊椎 - 胸部 - 脖子 - 头 (3)HIPS - UpLeg - Leg - foot - toe - toe_end 即,臀部 - 大腿 - 小腿 - 脚 - 脚趾 - 脚趾尖

Skinning 蒙皮 ###

这是给骨架附加网格的过程。蒙皮过程包括在你的网格中绑定顶点到骨骼,还有直接指定(硬绑定)或者混合多块骨骼的影响(软绑定)。不同的软件包使用不同的办法,比如,赋值给特别的顶点权重并且在网格上逐骨骼绘制影响到的顶点。最初的设定通常是自动化的,通过找最近的影响顶点或者使用“热度图”。蒙皮通常需要大量的工作并且使用动画测试来确保获得满意的皮肤变形效果。这个过程的一些指导准则如下:

  • 最开始使用自动蒙皮过程来设定皮肤(查看 3DS Maya 之类的相关教程);
  • 为你的骨骼创建一个简单的动画或者导入一些动画数据作为一个蒙皮结果的测试。这给你一个快捷的办法来评估你的蒙皮是否在运动中看起来很好;
  • 增量地编辑和细化你的蒙皮方案;
  • 坚持在软绑定的时候每个顶点最多使用 4 个骨骼,这是 Unity 支持的数目上限。如果超过 4 个骨骼,那么在 Unity 播放骨骼动画时至少会有一些信息被丢失;

4.2. 导入动画 Importing Animations ##

操作即知

4.3. 分割动画 Splitting Animations ##

一个动画化的角色典型地会在游戏中不同的情况有多个不同的动作。这些动作称为动画剪辑。比如,我们可能针对走路,跑步,跳跃,投掷,死亡之类有不同的动画剪辑。依赖于模型被动画化的方法,这些分离的动作可能作为不同的动画剪辑导入,或者当每个动作是简单的之前动作的延续时作为单个动画剪辑导入。在只有一个动画剪辑的情况下,这个剪辑必须用 Unity 分割成它的子组件剪辑,这会在你的工作流中引入一些其他步骤。

使用含有预先分割的动画的模型工作 ###

使用起来最简单的模型类型是那些包含了预分割动画的。如果你有一个像那样的动画,你将会看到一列可以在播放窗口中(inspector右下角)点击播放来预览的的动画剪辑,如果需要,帧范围可以被修改。动画导入器的 Inspector 中动画标签页会看起来像这样:

使用含有未分割动画的模型工作 ###

对于那些剪辑作为一个连续动画提供的模型,动画导入器 Inspector 中的动画标签页会看起来像这样:

像这样4合1的情况,你可以定义符合分离动画序列(走,跳之类)的帧范围。你可以通过按下+创建一个新的动画剪辑并且选择包含动画的帧范围。例如,走路动画在帧 0-33;跑动画在帧 41-57;踢动画在帧 81-97;

在导入设定中,分割动画表是你告诉 Unity 哪些在你资源文件中的帧构成一个动画剪辑的地方。你在这里指定的名字将会在你的游戏中用来激活它们。

PS:关于动画剪辑 Animation Clip ###

在项目视图中选择一个导入的动画

动画剪辑存储着所有可使用于角色动画或简单动画的动画数据,它们只有一个属性而且不能修改:采样率。这是创建剪辑的采样率。请注意,导入动画时,Unity 运行关键帧减少,因此这不是帧的数量。

注:导入动画无法在动画视图中进行编辑,但如果你在 Unity 复制一个导入动画,复制的导入动画可以编辑。

增加模型不包含的动画 ###

即使对那些没有肌肉定义的模型(也就是非 Mecanim),你也可以增加动画剪辑到动画组件中。你需要在动画属性中指定默认的动画剪辑,并且在 Animation 属性中指定可用的动画剪辑。你在这个非 Mecanim 模型中指定的动画也需要使用非 Mecanim 的方式(也就是说,肌肉定义属性应该被设置为 None)。

对于含有肌肉定义的模型(Mecanim),流程是不一样的:

  1. 创建一个新的动画控制器;
  2. 打开动画控制器窗口;
  3. 拖放想要的动画剪辑到动画控制器窗口;
  4. 拖放模型资源到层级视图;
  5. 增加动画控制器资源到资源的动画组件;

使用多个模型文件导入动画 ###

另外一种导入动画的方法是使用一个 Unity 允许的针对动画文件的命名方式。你创建不同的模型文件并且使用“模型名@动画名.fbx”的命名约定。比如,对一个叫“goober”的模型,你可以分别导入空闲,走路,跳跃和踢墙跳跃动画使用命名为“goober@idle.fbx”,“goober@walk.fbx”,“goober@jump.fbx”和“goober@walljump.fbx”的文件。这些文件中只有动画数据会被使用,即使原有文件是同网格数据一起导出的。

Unity自动导入所有4个文件并且收集所有的动画到没有@标记的文件中。在上面的例子中,goober.mb文件将会自动建立到空闲,跳跃,走路和踢墙跳的引用。对于FBX文件,简单的导入一个没有动画的模型文件(也就是,goober.fbx)和4个命名为goober@动画名.fbx的剪辑,为每个文件导出想要的帧(在FBX对话框中选择)。

4.4. 如何获取类人模型 ##

这里有三种重要的途径来获取用于 Mecanim 动画系统的类人模型:

  1. 使用一个程序化角色系统或者角色生成器诸如 Poser,Makehuman 或者 Mixamo。其中一些系统会为你的网格搭骨架和蒙皮(比如,Mixamo)但是另外一些不会。此外,这些方法可能需要你减少原有网格上的面数来适应 Unity;
  2. 从 Unity Asset Store 购买演示示例和角色内容;
  3. 可以从草图开始准备自己的角色;

4.5. 导出和验证 ##

Export & Verify

Unity 可以导入大量各式各样通用的本地 3D 文件格式。我们推荐的导出和验证你模型的格式是 FBX2012 因为这样可以:(1)导出带骨架层级的网格,法线,纹理和动画;(2)重新导入进你的 3D 包来更验证你的动画模型;(3)导出不带网格的动画;

5. 创建 Avatar #

在FBX导入之后,你可以在 FBX 导入器选项中的 rig 标签页指定是哪种类型的骨架。

5.1. 类人动画 Humanoid animations ##

对于类人骨架,选择 Humanoid 然后单击 Apply.Mecanim 将会尝试匹配你的骨骼结构到 Avatar 骨骼结构。在大多情况下,它可以自动地分析骨骼之间的链接来完成这一过程。如果匹配成功,你将会在 Configure… 按钮旁边看到一个对号

并且,在成功匹配的情况下,一个 Avatar 子资源会被增添到 FBX 资源,可以在项目视图中看到它。

如果 Mecanim 不能创建 Avatar,你将会看到一个叉号出现在 Configure… 按钮旁边,并且没有 Avatar 子资源被添加。当这种情况发生的时候,你需要手动配置 Avatar。

5.2. 非类人动画 Non-humanoid animations ##

提供了 2 种非类人动画:通用和旧版。通用动画是使用 Mecanim 系统导入但是不会获得类人动画的额外好处。旧版动画是使用 Unity 在 Mecanim 之前提供的动画系统。还有一些情况下旧版动画系统是有用的(大多是你不想完全更新项目的情况)但是他们很少在新的项目中使用。

6. 配置 Avatar #

Avatar 是 Mecanim 的一个如此重要的部分,它需要被配置以符合你的模型。因此不论自动 Avatar 的创建失败或者成功,你都需要进入 Avatar 配置模式来确保你的 Avatar 是有效并且合适地配置了。你的角色骨骼匹配 Mecanim 的预定义骨骼结构并且模型是 T 字形姿势是非常重要的。

如果自动 Avatar 创建失败,你将会看到一个叉号出现在 Configure 按钮旁边。

如果它成功了,你将会看到一个对号出现在 Configure… 按钮旁边:

在这里,成功仅仅意味着需要的骨骼被匹配上了,但是为了获得更好的结果,你可能会想也匹配上可选的骨骼以及让模型进入一种合适的 T 字姿势。当你进入 Configure… 按钮,编辑器将会问你是否保存场景。之后进入 Configure 模式,场景视图用来单独显示指定模型的骨骼,肌肉和动画信息,不显示场景的其他部分。一旦你保存了场景,你就会看到一个带有骨骼映射的新 Avatar 配置检视器。

检视器显示哪些骨骼是需要的还有哪些骨骼是可选的 - 可选的骨骼的运动可以自动用插值计算出来。为了让 Mecanim 产生有效的匹配,你的骨架需要至少含有必须的骨骼在适当的位置。为了提高查找匹配 Avatar 的机会,可以使用反映身体部位的名称命名你的骨骼(像 “LeftArm”“RightForearm” 这样的名称都是合适的)。

如果模型没有产生一个有效的匹配,你可以手动按照类似 Mecanim 内部的处理方式做一下:

  1. Sample Bind-pose 采样绑定姿势(尝试让模型更接近它建模时候的姿势,一个合理的最初姿势);
  2. Automap 自动映射(从最初的姿势创建一个骨骼映射);
  3. Enforce T-pose 强制 T 字姿态(强制让模型更接近 T 字姿态,这是 Mecanim 使用的默认姿势);

如果自动映射(Mapping->Automap)完全或者部分失败,你可以通过从场景或者体系结构视图拖拽它们来赋值到骨骼。如果 Mecanim 认为骨骼合适,它会用绿色在 Avatar 检视器中显示,否则会以红色显示。最后如果骨骼被正确赋予了,但是角色不是在正确的姿势,你将会看到消息 “Character not in T-Pose(角色不是在T字姿态)”。你可以尝试 Enforce T-pose(强制 T 字姿态)或者旋转余下的骨骼到 T 字姿态。

7. 肌肉设定 Muscle setup #

Mecanim 允许你使用肌肉(Muscles)控制不同骨骼上的各种动作尺度。一旦 Avatar 正确配置了,Mecanim 将会“理解”骨骼的结构并且允许你开始在 Avatar 检视器中的 Muscle 是标签栏中开始工作。这里,很容易调整角色的动作尺度并且确保角色使用逼真的方式扭曲,避免过度造作和自我重叠。你可既可以在 body (视图下部)来调整单独的动画或者使用预先定义的一次操作若干骨骼的扭曲(视图上部)来操作角色。

Muscle Clips 肌肉剪辑

在 Animation 标签栏,你可以建立肌肉剪辑(Muscle Clips),它是针对特定肌肉或者肌肉组的动画。

你也可以定义肌肉动画应用到身体的哪个部分。

8. 阿凡达(替身)身体遮罩 Avatar Body Mask #

在动画中,身体的特定部分可以被有选择性的激活或禁用,这就是所谓的身体遮罩。身体遮罩在模型导入检视面板中的动画选项卡中和 Animation Layersd (动画图层)中被应用。身体遮罩可以让你通过对角色的动画编辑去适应一些特殊需求,使角色更接近特殊需求。比如说,你可能有一个站立行走动画包含了手和脚的运动,但是如果角色是用双手抬着一个超大的东西然后你不想他在走路的时候手臂摆动。无论如何,你还是可以使用站立行走动画然后在身体遮罩功能中屏蔽掉手部动作。

身体包括这些部分:头部,左手臂,右手臂,左手,右手,左腿,右腿和根部(根部表示为脚底的影子那部分)。在身体遮罩中,你还可以选择给手和脚添加反向动力学(IK),这将会决定 IK 曲线是否会被包含在动画混合中。

  • 点击身体部分切换包含或排除(绿/红);
  • 在身体周围的空白区域双击来切换所有身体遮罩在身体遮罩检视面板中(手臂已经排除了);

在网格导入检视面板的动画标签中,你会看到一个名为 Clips 的列表,它包含所有对象的动画剪辑。当你选择列表的其中一项时,会有选项显示出来,包括身体遮罩编辑器。当然你也可以创建一个身体遮罩资源(Assets->Create->Avatar Body Mask),文件在磁盘中后缀是.mask 身体遮罩资源可以在动画控制器中被重复使用,当指定了动画图层时。

使用身体遮罩的好处是他有助于减少内存开销,因为不活跃的部位不需要激活相关的动画曲线。而且,未使用的曲线,不需要在动画播放过程中计算了,这往往会减少动画播放中的 CPU 开销。

9. 为类人动画重新定位目标 Retargeting of Humanoid animations #

Mecanim 的最强大的功能之一:重定目标的仿人机器人动画。这意味着你可以相对轻松的把相同的动画应用到各种角色模型上。重定目标才有可能为人形机器人的模型,在哪里阿凡达已配置,因为这给了我们的模型的骨骼结构之间的对应关系。

Recommended Hierarchy structure 推荐的层次结构, 使用 Mecanim 的动画时,你可以预料你的场景包含以下元素:

  • 导入的角色模型,附带了一个 Avatar;
  • 动画设计组件,引用了一个动画设计控制器资源;
  • 一个动画剪辑,引用自动画设计控制器;
  • 为角色编写的多个脚本;
  • 与角色相关的组件,比如角色控制器;

项目还应包含不同的角色模型,并且模型上附带着一个有效 Avatar。

9.1. 推荐的设置 ##

  1. 在层级面板中创建一个包含角色相关组件的 GameObject;
  2. 把模型作为 GameObject 的子物体,赋予动画设计组件;
  3. 确保脚本引用到子物体上的动画设计组件而不是根部上的;使用 GetComponentInChildren() 代替 GetComponent();

然后,为了重用另一个模型的动画,需要这样做:

  1. 禁用掉原始模型;
  2. 把所需的模型扔给 GameObject 作为子物体(下图中的 MainChar 物体);
  3. 请确保为新模型的动画设计控制器引用相同的控制器资源文件(下图中第一个属性);
  4. 在顶级的 GameObject 中稍微调整一下角色控制器、 变换和其他属性,并确保动画顺利工作在的新模式;

10. 为角色赋予生命 Bringing Characters to Life #

10.1. 循环动画剪辑 Looping animation clips ##

每个使用动画的人都需要执行一个基本的操作,那就是确保他们的循环是正确的。这十分重要。举个例子来说,当一个动画剪辑是用来表示行走循环的,那么开始帧和结束帧需要是同样的一个造型(比如左腿在地面上),确认脚底没有滑动,或者一些奇怪或愚蠢的动作。Mecanim 为检查这些提供了一些方便的工具。动画剪辑可以给予造型,旋转和位置进行循环。

如果你在动画剪辑上拖拽开始或结束点,你将会看到对于每个可能的循环参数,Mecanim 都提供了一套合理的循环曲线。如果你在那些绿色的曲线位置放置了开始/结束标识,那么这个动画就更可能会正确的循环。循环匹配指示器(loop match)会检测你所选择的范围有多符合正确的标准。当循环匹配指示器是绿色的时候,激活 Loop Pose(比如)将会确保这个造型看起来是自然的。下面右边为正确的循环。

10.2. 动画组件和动画控制器 Animator Component and Animator Controller ##

任何一个拥有 avatar 的 GameObject 都将拥有一个 Animator 组件用来连接角色和他的行为。

Animator 组件声明了一个 Animator 控制器,用来设置角色上的行为。这些包括状态机、混合树和通过脚本控制的事件。

有以下属性:

  • Controller 控制器 : 添加在当前角色上的Animator控制器;
  • Avatar 阿凡达 : 当前角色的Avatar系统;
  • Apply Root Motion 使用根运动 : 是否使用角色自身动画运动属性移动角色位置或者使用脚本控制;
  • Animate Physics 物理动画 : 动画是否使用物理交互;
  • Culling Mode 剔除模式 : 动画的剔除模式;
  • Always animate 总是使用播放动画 : 总是播放动画,不做任何剔除;
  • Based on Renderers 基于渲染器 : 当渲染器不见时,只有根运动被执行。身体的其他部分在角色不可见时都保持静止;

可以从动画控制器视图(菜单:Window > Animator Controller)预览和设置角色行为 : Animator 控制器可以从工程视图内创建(菜单: Create -> Animator Controller)。在状态机设置完毕后,可以拖拽这个控制器到任意一个检视器中拥有 avatar 角色的 Animator 组件内。

动画控制器窗口包括:

  • 动画层组件;
  • 事件参数组件;
  • 状态机自身的可视化窗口;

注意一点,Animator 控制器窗口总是会显示最近选择的资源中的 .controller 状态机,无论当前是哪个场景被载入。(根据测试,控制器窗口也会在选择附加了 Animator 组件的 GameObject 上的控制器时进行切换)

10.3. 动画状态机 Animation State Machines ##

一个角色拥有多个可以在游戏内在不同状态下调用的不同动作是一件很普遍的事。比如,一个角色可以在等待时呼吸或者摇摆,在得到命令时行走或者从一个平台掉落时惊慌地伸手。当这些动画进行回放时,使用脚本控制它们可能是一个潜在的复杂工作。Mecanim 借用了电脑工程师熟知的一个概念 —— 状态机 —— 来简单的控制和序列化角色动画。

一个最基本的观点是:一个角色应该在任何给定的时刻执行某些特定的动作。这些动作是否可用是基于游戏进程的,但是典型的动作包括等待,移动,跑动,跳跃等。这些动作被称为状态。在场景中当角色正在行走、等待或者做其他什么的时候都会处于某一个状态。一般来说,角色在进入下一个状态时会被限制,而不是可以从任意一个状态跳转至另一个任意状态。比如,一个“跑动跳跃”动作只可以在角色正在跑动时执行而不是当角色正在站立的时候。你永远不应该从等待动作中直接跳转到跑动跳跃动作状态。让角色从正确跳转状态的选项被称为状态转移。而将上面这些(状态的集合,状态转移的集合和一些用于记录正确状态的变量)整合起来的东西就是一个状态机。

状态和状态转移可以使用图形界面描述,在这个界面里,节点用来描述状态而带箭头的线段用来描述状态转移。你可以认为当前的状态(被标记或高亮的某个节点)只可以沿着这些箭头方向转移至其他状态。

状态机对于动画的重要性在于他们可以很简单地通过相对较少地编码完成设计和更新。每个状态都有一个当前状态机在那个状态下将要播放的动作集合。这将允许动画师和设计师不使用代码而定义可能的角色的动画和动作序列。

Mecanim状态机 : Mecanim 的动画状态机提供了一种可以预览某个独立角色的所有相关动画剪辑集合的方式,并且允许你能够在游戏中通过不同的事件触发不同的动作。动画状态机可以通过动画状态机窗口进行设置,而这个窗口看起来像是这样:

状态机包括状态、状态转移和事件,并且在大的状态机中可以设置一个小的子状态机。

动画状态 Animation States ###

动画状态是动画状态机中内建的基本模块。每个状态包含一个在该状态下角色所能播放的独立的动画序列(或是一棵动画混合树)。当游戏中触发一个状态转移事件时,角色将会转移至动画序列指定的下一个状态中。当你在动画控制器中选择一个状态时,你将会在检视器中看到一些关于这个状态的参数。

  • Speed 速度 : 动画的默认速度;
  • Motion 动作 : 这个状态的动画剪辑;
  • Foot IK 脚部动画约束 : 是否在这个动作使用脚部动画约束;
  • Transitions 状态转移 : 从这个状态产生的状态转移;

当状态机第一次被激活时将会自动跳转至使用褐色显示的默认状态。如果必要的话你可以更改默认状态,在另一个状态上右击,并在弹出菜单中选择“设置为默认状态”(Set As Default)。每个状态转移后的 solo 和 mute 复选框用来控制动画预览的行为. 你可以在动画控制器窗口的空白区域右击,并在弹出菜单中选择“建立状态”->“控状态”(create state -> empty)来创建任意一个新的状态。或者你也可以通过向动作控制窗口拖拽一个新的动画来创建一个包含该动画的动画状态。(注意:你只能拖拽一个 Mecanim 系统动画,非 Mecanim 系统动画将被状态机拒绝)动画状态也可以包含一颗动画混合树(Blend Tree)。

任意状态是- 一个一直存在的特殊状态。他的存在是为了保证你在无意转移至某个你当前正处于的特殊状态而准备的。为你的状态机中的每个状态设置相同的对外转移是一个快捷的方式。注意:这里 Any State 所暗示的特殊含义是指:它不能成为一个状态转移的终点。(比如,跳转至“任意状态”不是做选择一个随机状态跳转)。

动画状态转移 Animation Transitions ###

动画转移发生在:在你从一个动画状态跳转至另一个动画状态时。在任意时刻只可能有一个动画状态转移被激活。

  • Atomic 原子操作 : 这个转移是否是一个原子操作(不可被中断的);
  • Conditions 触发条件 : 这里我们决定什么时候这个转移被触发;

触发条件包括 :

  • 一个参数条件, 你可以使用“结束时刻(Exit Time)”作为一个参数,并且声明一个表示为源状态标准时间参数(比如,0.95 表示这个状态转移将会在原动画播放至 95% 的时刻触发)。
  • 一个条件谓词(如果需要的话,比如使用float作为参数时可以使用小于/大于(Less/Greater))。
  • 一个条件值(如果需要的话)。

可以通过拖拽开始或结束之间的重叠区域来调整这个状态转移。

动画参数 Animation Parameters ###

参数可以使用脚本通过 Animator 类的:SetVector, SetFloat, SetInt 和 SetBool 进行设置。这是一个通过用户输入修改参数的例子。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
using UnityEngine;
using System.Collections;

public class AvatarCtrl : MonoBehaviour {

protected Animator animator;

public float DirectionDampTime = .25f;

void Start ()
{

animator = GetComponent<Animator>();
}

void Update ()
{

if(animator)
{
//get the current state
AnimatorStateInfo stateInfo = animator.GetCurrentAnimatorStateInfo(0);

//if we're in "Run" mode, respond to input for jump, and set the Jump parameter accordingly.
if(stateInfo.nameHash == Animator.StringToHash("Base Layer.RunBT"))
{
if(Input.GetButton("Fire1"))
animator.SetBool("Jump", true );
}
else
{
animator.SetBool("Jump", false);
}

float h = Input.GetAxis("Horizontal");
float v = Input.GetAxis("Vertical");

//set event parameters based on user input
animator.SetFloat("Speed", h*h+v*v);
animator.SetFloat("Direction", h, DirectionDampTime, Time.deltaTime);
}
}
}

10.4. 混合树 Blend Trees ##

一个游戏动画的基本任务就是将两个或多个相似的动作混合。也许最广为人知的例子就是依照任务行动的速度将行走和跑动动画混合起来了。另一个例子就是角色在跑动中向左或向右转身。区分状态转移和混合树是很重要的。虽然两者都被用来制作平滑动画,但是他们是分别在不同的情况下使用的。

  • 状态转移是在确定的时间内从一个动画状态平滑的转移至另一个时使用的。状态转移被认定为动画状态机的一部分。如果一个动作跳转到另一个完全不同的动作耗时很短,那么状态转移通常的表现令人满意。
  • 动画混合树是通过使用不同的角度将角色不同的部分混合达到平滑混合不同的动画的目的的。他会用一个有动画控制器有关的、可量化的混合参数来控制各个动作相对于最终的效果的权重。为了使混合过后的动作起作用,必须混合造型和时间相近的动作。动画混合树在动画状态机中是一个特殊类型的状态。

一个相似动画可以被多样化的例子就是走动与跑动动画。为了让混合工作良好,需要在标准时间下确保动画剪辑是在相同的点发生转移的。比如,走动和跑动可以都在脚与地板接触的时刻进行连接(比如,左脚在 0.0 时刻而右脚在 0.5 时刻)。标准时间之所以被使用,是因为这样就可以无视动画剪辑是不同长度这件事了。

使用混合树进行工作,你需要 :

  1. 在动画控制器窗口的空白处右击;
  2. 在弹出菜单中选择“新建状态”-> “通过新的混合树创建”(Create State –>From new Blend);
  3. 双击混合树后进入混合树界面;

现在动画控制器界面展示了整棵混合树,而检视器则显示了当前选中的节点和他的直系子节点。下面的动画控制器窗口展示了一个完整的混合树。左半部分是一个只有根节点的混合树,右半部分是一个拥有一个根节点和三个子节点(三个动画剪辑)的混合树。

这里显示了一个可视化窗口,这个窗口演示了如何通过调整参数值来改变动画之间的混合的(当你拖拽滚动条的时候,混合树根上的箭头会通过调整连线的光影效果来表示动画剪辑之间的影响权重)。

你可以选择一个混合树上的任意一个节点,从而在检视器上检视该节点。如果你选择了一个动画剪辑节点,那么检视器上将会显示一个动画剪辑。这些从模型上导入的动画剪辑信息是只读的。如果你选择的是一个混合树节点,那么检视器上将会显示混合树信息。

混合模式下拉菜单是用来选择这个混合树是使用一个参数或两个参数来进行混合的。

一维混合 1D Blending ###

混合节点在检视器中的第一个选项是混合类型。这个下拉菜单是用来选择使用一个或两个参数进行混合的混合模式。1D 混合使用一个参数对子行动进行混合。在设置完混合模式后,你需要做的是选择一个你要在混合树中控制的动画参数。比如,方向(direction)参数需在 -1.0(左)和 +1.0(右),使用 0.0 将会向正前方跑动。之后你可以通过点击“添加动作区域”(Add Motion Field)来为混合树添加一个单独的动画剪辑。当你完成后,可能检视器看起来像是这样:一个拥有三个动画剪辑的1D混合节点。

这个动作示意区域显示了每一个子动作在调整参数处在该子动作最小值和最大值的之间时,该子动作对整个动作提供的影响。每一个动作被显示为一个蓝色小金字塔(第一个和最后一个动作只显示了一半),如果你在其中一个上点住鼠标,你会发现其对应的动作会在下面的动作列表里被高亮。每个小金字塔的峰值表示这个子动作在这时对整个动作产生完整的影响,或者意味着这时候动画的权重为1并且其他所有动画的权重为0.这也被称为整个子动作的临界值。混合节点检视器窗口中,根据参数的范围将各个子动作的权重可视化。

红色的竖直条标识了参数的值。如果你点击检视器底部预览框上的播放按钮,并在动作示意区域左右拖动红色竖直条,你可以发现那些参数值是如何在不同的动作间通过不同的参数调整混合的。

在混合节点示意区域下面显示的左右两个数字就是调整参数的范围。他们中的每一个值都可以通过点击拖拽鼠标进行更改。注意:这个值需要符合动作列表中第一个和最后一个子动作的临界值限制。

你可以通过在示意区域点击和左右拖拽对应的蓝色小金字塔来调整动作临界值。如果“自动设置临界值”(Automate Thresholds)选项没有被勾选,你可以从动作列表中的对应子动作的临界值编辑框内输入调整临界值。

在动作列表下面的是“自动设置临界值”(Automate Thresholds)复选框激活他将会将临界值均匀的分布在调整参数范围内。比如,如果有五个动画剪辑分布在 -90 到 +90 的范围内,那么他们的临界值会被分别设定为 -90,-45,0,+45 和 +90。“计算临界值”(Compute Thresholds)下拉菜单可以通过拥有根动作的动画剪辑所包含的数据设置临界值。可用的选择包括速度,X、Y、Z 方向分量速度和使用弧度或角度计算的角速度。如果你的参数符合上述某个属性,你可以选择下拉菜单中的某项。

  • Speed 速度 : 根据速度设置临界值(速度的大小)。
  • Velocity X X方向速度 : 根据x方向分量速度设置临界值。
  • Velocity Y Y方向速度 : 根据y方向分量速度设置临界值。
  • Velocity Z Z方向速度 : 根据z方向分量速度设置临界值。
  • Angular Speed (Rad) 角速度(弧度): 根据每秒转过的弧度计算临界值。
  • Angular Speed (Deg) 角速度(角度): 根据每秒转过的角度计算临界值。

打个比方说:你有一个走动动画,他每秒移动 1.5 个单位,而一个慢跑动作每秒移动 2.3 个单位,而一个跑动动作每秒移动4个单位。选择下拉列表中的“速度”(Speed)选项可以基于这个值为三个动画配置参数范围。所以你看到参数设置为了 3.0,混合了慢跑和跑动动画,并且(临界值)稍微偏向慢跑一些。

二维混合 2D Blending ###

混合节点在检视器中的第一个选项是混合类型。这个下拉菜单是用来选择使用一个或两个参数进行混合的混合模式。2D 混合使用两个参数对子行动进行混合。

2D 混合类型使用了一套适应自身的不同使用方法。他的不同点在于:每个子动作都在对整个动作产生影响。

  • 2D 简单定向 2D Simple Directional : 当你的动作表现为不同的方向(就像“向前走”、“向后走”、“向左走”和“向右走”,或“”“朝向上”、“朝向下”、“朝向做”和“朝向右”)时,你可以使用这个混合类型。当然你可以选择“等待”或者“朝向前”作为原点动作。在简单定向模式中应该尽量避免使用相同朝向的动作,比如“向前走”和“向前跑”。
  • 2D 自由定向 2D Freeform Directional : 这个混合类型同样也用于混合朝向不同的动作,虽然你也可以混合像“向前走”和“向前跑”这样的动作。在自由定向模式下,动作集合一般都应该有一个位于原点的动作,比如“等待”。
  • 2D 自由笛卡尔坐标 2D Freeform Cartesian : 这种模式最好使用在你的各个动作间没有明显朝向区别的时候。在使用自由笛卡尔坐标时,你可以在X轴和Y轴上分别使用不同的定义,比如“角速度”和“线速度”。比如这样一些子动作:“向前走动不转弯”、“向前跑动不转弯”、“向前走动转向右”、“向前跑动转向右”等。

在设置完毕混合模式之后,你需要做的第一件事就是选择两个动画参数来控制这棵混合树。在例子中,选择的参数是 X 方向速度分量(旋转)和Z方向速度分量(向前速度)。你可以通过点击 “+”-> 添加动作区域(Add Motion Field)来为混合树添加一个动画剪辑。当你完成这些以后,你可以看到想这样的一个检视器 : 这是一个由五个动画剪辑的2D混合节点。

2D 混合中的位置(position)就像是 1D 混合中的临界值(thresholds)一样(除了 2D 中使用两个参数代替了 1D 中的一个以外)。位置中的水平 X 轴对应第一个参数,而垂直 Y 轴对应第二个参数。一个向前移动动画可能有 0 速度的 X 分量和 1.5 速度的 Z 分量,所以应该把这些值写在动作 Pos X 和 Pos Y 的对应数值区域内。

The 2D Blending Diagram 2D 混合示意区域

在检视器的 2D 混合区域顶部是显示所有子动作位置的示意区域。子动作被显示为一个蓝色的点。那些没有动画剪辑加载或对混合树没有影响的点被显示为灰色的点。你可以通过点击示意区域中的那些点选择一个子动作。一旦你选择了某个子动作,那个子动作的对整个动作的影响将会用蓝色的区域显示。越接近动作点所在位置的区域,该子动作的影响越强烈。当参数点处于动作点时,该子动作(对整个动作)产生完整影响,这意味着这个动画剪辑的权重是 1 而其他任何动画剪辑的权重都是 0。

红色的点标识了两个参数。如果你点击检视器底部预览框上的“播放”(Play)按钮,并且四处拖动这个红色的点,你就能看到这个参数的值是控制不同动作值之间的混合的。在示意图中你可以看到每个动作的影响力被显示成一个以动作点为圆心的圆形。如果你移动那个红色的点到某个蓝色的动作点上,那么这个蓝色点上的圆的半径编程最大,而其他的点上的圆形都消失了。而(将红色的点置于)一些动作的中间的位置的时候,越靠近红色的点的子动作在混合过程中占据更大的影响。如果你为了看到某个动作的影响区域选定一个子动作后,当你拖动红色的点时,(你会看到)该动作上对应的圆圈的大小和红色点所处位置的影响区域强度是对应的关系。

当没有动作被选择的时候,示意区域显示了一个所有影响区域叠加的效果 : 蓝色很深的位置被一个单独的动作控制,而蓝色较浅的部分则通过多个动画混合。

Position 位置

你可以通过点击拖动某个示意区域中的蓝色动画点来改变他的“位置”。你也可以通过编辑动作列表中的 Pos X 和 Pos Y 列中的数字来直接改变他们。

“计算位置”(Compute Positions)下拉菜单将会设置根据你导入模型中的根动作自动选择设置位置的值。可选的数据包括速度,x、y、z 方向速度分量,和基于角度或弧度的角速度。如果一个或者全部两个参数符合上面那些属性,你可以使用“计算位置”下拉菜单计算 Pos X 和 / 或 Pos Y 的值。

  • Velocity XZ XZ速度 : 每个动作的 Pos X 根据 X 方向分量设置;Pos Y 根据 Z 方向分量设置。
  • Speed And Angular Speed 速度和角速度 : 每个动作的Pos X根据角速度(每秒角度)设置;Pos Y 根据速度设置。

另外,你可以通过只选择“计算位置” ->“ 从…计算X位置”(X Position From)和/或 “计算位置” ->“ 从…计算Y位置”(Y Position From)分别计算每个分量,并保持另一个分量不变。

举个例子,你可以根据侧向移动和前向移动分别设置两个参数,这样你就会在平均速度(0, 0, 0)处得到一个等待动画,在(0, 0, 1.5)处得到一个走动动画,并且在(-1.5,,0, 0)和(1.5, 0, 0)处得到两个平移动画。从下拉菜单中选择 “XZ速度”(Velocity XZ)选项将会根据 X 和 Z 方向分量速度设定动作的位置。

11. Mecanim 进阶主题 Mecanim Advanced topics #

11.1. 使用 Mecanim 的动画曲线 ##

动画曲线可以在动画导入设置的动画标签中添加进动画剪辑。

曲线的X周标识为标准时间并且他的值总是处于 0.0 到 1.0(仅根据各自动画剪辑的开始或结束确定,忽略动画本身的持续时间)。

双击动画曲线会打开可以为曲线添加关键帧的标准 Unity 曲线编辑器(如下图)。关键帧是一些沿着动画曲线分布在时间轴上的点,这些点可以通过 Animator 直接精确调整来代替直接插值。关键帧在标记某些重要的点时十分有效。比如对于一个走动动画,你可以标记左脚着地的点,之后是两脚都在地上,再然后是右脚在地上等等。当关键帧被建立起来后,你可以通过点击 “前一/后一关键帧” 按钮在两帧间切换;你在文本框中输入的值会被设置为所选中的关键帧的值。

如果你有一个 Animator 控制器参数同名的曲线,那么这个参数会根据曲线的时间线调整这个参数的值。例如,你有一个脚本调用了 GetFloat,那么返回值会等于调用时刻曲线上的值。注意:在任意时刻可能都会有多个动画剪辑试图通过相同的控制器设置相同的参数。这时,曲线的值会通过各个动画剪辑混合。如果一个动画没有为某个参数设定任何曲线,那么混合将使用这个参数的默认值。

11.2. 子状态机 Sub-State Machines ##

一个角色拥有某些由多个状态组成的复杂动作是很普遍的。与其将这些事件制作成一个状态,一个更有效的办法是标记这些独立的状态,并且将每个状态分开。比如,一个角色可能有一个被称为 “Trickshot” 的动作:首先下蹲瞄准,然后射击,最后重新站起来。( “Trickshot” 动作状态序列 )

尽管这样做能够达到控制的目的,但是之后状态机会变得很庞大,并且随着更多的复杂动作地添加将会变得越来越臃肿。当然,你可以利用编辑器里的空白区域将相关的状态简单的分开。然而 Mecanim 的功能在这些的基础上会更进一步:你可以在状态机中将一组状态轻松的收缩至一个单独命名的控件里。这组被收缩的状态被称为 子状态机

你可以在 Animator 控制窗口的空白区域右击,从弹出菜单中选择“创建子状态机”(Create Sub-State Machine)从而创建一个新的子状态机。子状态机使用一个长的六角形表示,以区别于其他普通的状态。下图是一个子状态机 :

当双击那个六角形时,编辑器会刷新以便你像编辑一个完全分离的状态机那样编辑这个子状态机。在顶部显示的一个“导航路径”显示了当前所编辑的子状态机(注意:你可以为子状态机创建新的子状态机)。点击某个条目将会使编辑器转至那个子状态机。

External transitions 外部状态转移

就像之前提到的那样,子状态机是一个将一组相关状态在编辑器中收缩起来的一个途径。所以当你将状态转移至一个子状态机时,你必须选择一个你希望连接的状态(以供连接)。

你会发现在子状态机中有一个以“上层”(Up)作为前缀的额外状态。

这个“上层”(Up)表示“外部世界”,在视图中状态机包含整个子状态机。如果你为子状态机的某个状态添加一个指向“上层”(Up)状态的状态转移,你需要指定一个外部状态机的状态以供连接。下图为连接至外部状态机的状态。

11.3. 动画层 Animation Layers ##

Unity 使用“动画层”来管理身体不同部分的复杂状态机。比如:你可以使用下半身(动画)层来管理走动/跑动;使用上半身(动画)层来控制投掷/设计动作。可以使用Animator控制器左上角的层权重来管理动画层.

你可以点击控件上的“+”添加新的动画层。你可以在每层上指定特定的身体蒙皮(将会应用动画的身体部分)和混合类型。(混合类型中的)“重载”(override)表示其他层的信息会被忽略;“附加”(additive)表示这些动画将被附加在之前的层上。

“蒙皮”(Mask)选项用来指定该层使用的身体蒙皮。比如:如果你希望当角色走动或跑动的时候,让上半身完成投掷动作,你可以使用上半身蒙皮。就像这样:

Animation Layer syncing 动画层同步

有些时候在不同层中能够重用一些相同的状态机是很有用的。比如:如果你希望模拟一个“负伤”的行为,并且这个“负伤”的动画是为代替走动/跑动/跳动中“健康”(的动画)。你可以点击某个层上的“同步”(Sync)复选框,并且选择你希望同步的那一层。这样的话,这些状态机结构将会保持一致,但是实际的动画剪辑会有区别。

11.4. 动画状态机预览(独立 和 关闭) Animation State Machine Preview (solo and mute) ##

Solo 和 Mute 的功能 ###

  1. 如果选择了mute,那么被选择的状态转移一定会被禁用;
  2. 如果不选择solo,在没有变量控制(结束条件为“exit time”)的情况下,该状态优先选择动作列表中最前(或者说最上的)的状态转移;
  3. 如果选择了某个solo,那么在没有变量控制(结束条件为“exit time”)的情况下,优先选择标记solo的状态转移;
  4. 如果有多个状态转移选中了solo,那么优先选择这些已选中solo的状态转移中,在动作列表中靠前的状态转移;
  5. 暂未实验使用参数控制的转移情况。

solo 状态转移被显示为绿色,mute 状态转移被显示为红色,就像这样:

在上面的例子中,如果你处于状态 0 中,那么只有状态 A 和状态 B 可以使用。

  • 基本的原则是,如果一个状态被标记为 solo,那么其余的状态转移将被视为选中 mute;
  • 如果 solo 和 mute 同时被选中,那么 mute 的优先级更高(即视为只选中了 mute);

PS : 现在的控制视图并不总是响应引擎的内部 mute 状态

11.5. 目标匹配 Target Matching ##

在游戏中,有一种情况经常发生,就是在某个时刻你需要某个角色的手或者脚到达某个特定位置。比如说,某个角色需要在跳过踏板的时候抓住头顶上的某个横梁。你可以用 Animator.MatchTarget 函数来解决这种情况。比如说,你有一个叫做“跳跃起来”(jump up)希望处理一个角色跳到平台上的情况时,你可以尝试下面的做法:

  • 找到角色在动画剪辑中跳起时刻的位置。注:在这个例子中(这个位置是)画片段标准时间的0.141或者总动画时间的14.1%。

  • 找到角色在动画剪辑中叫着地的位置。注:这个例子中(这个位置的)值是 78.0% 或者 0.78。

  • 建立一个名为(TargetCtrl.cs)的脚本,这个脚本产生一个 MatchTarget 函数调用,就像这样:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    using UnityEngine;
    using System;

    [RequireComponent(typeof(Animator))]
    public class TargetCtrl : MonoBehaviour {

    protected Animator animator;

    //the platform object in the scene
    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), 0.141f, 0.78f);
    }
    }
    }

将这个脚本附加在 Mecanim 模型上。

这个脚本将会移动角色,这样他就能从正确的位置起跳,并且他的左腿会落在目标点上。记住:目标匹配通常只有在游戏运行的正确位置调用才会生效。

11.6. 根动作-如何工作 Root Motion - how it works ##

身体变换是角色的质心(质量中心)。它被 Mecanim 用来做引擎重定向和支持大多数稳定的可替换模型。身体方向是根据 Avatar 系统中 T 姿势的上半身和下半身方向平均值得到的。身体变换位移和角度被存储在动画剪辑中(使用 Avatar 系统的肌肉定义设定完成)。而且只在动画剪辑中保存世界空间曲线。其他还包括:既有曲线和目标 IK(手和脚的)都被存储在身体变换中。

Root Transform 根变换 ###

根变换是一个预测位置,他会根据身体 Y 平面预测并且在运行时计算的。根变换会在每一帧中被计算。并且他会在 GameObject 令他移动时改变。

Animation Clip Inspector 动画剪辑检视器 ###

动画剪辑编辑器可以通过设置“根旋转变换”、“根位置变换(Y)”和“根位置变换(XZ)”让你可以根据身体变换来控制根变换的预期位置。根据这些设定,某些身体变换可能就是根变换。比如,在某个动作中Y的位置是根动作(轨道)或者某个已知被烘焙进姿势(身体变换)的一个部分时。

Root Transform Rotation 根旋转变换 ###

烘焙进姿势(Bake into pose):旋转需要保留在身体变换(或姿势)中。根旋转需要是连续的并且步长相同。这意味着 GameObject 不能在任意的动画剪辑中被旋转。

只有拥有相似根方向起点和终点的动画剪辑可以使用这个选项。你需要在界面上显示一个绿灯,这样就说明这个动画剪辑是一个可用的备选片段。一个合适的备选片段例子:一个向前行走(片段)和一个奔跑(片段)

基于(Based Upon):这允许你设置片段的旋转。通过使用身体朝向,动画剪辑会跟随身体朝向向量旋转。这个默认设置在大多数类似走动、跑动和跳跃之类的捕捉动作数据中会很好的工作,但是他将会在类似扫射这种和身体朝向向量垂直的动作中失效。在那些情况下你可以手动调整偏移(Offset)设置。最终你可以自动添加导入片段的作者创建的原件。通常情况下,这是根据美工设定的基于旋转的关键帧数据来使用的。

偏移:当使用“基于”选项时手动添加的偏移值。

Root Transform Position (Y) 根位置变换(Y) ###

这个选项使用和根旋转变换相同的概念。

烘焙进姿势:动作的 Y 组件将会保留在身体变换(姿势)中。根变换中的Y组件将会保持不变,根位置中的Y的步进值将会是0.这意味着这个片段不会改变 GameObject 的高度。同样的你需要看到一个绿灯来告诉你这样烘焙Y动作进姿势是一个可用的备选。

大部分动画剪辑会激活这个设定。只有那些需要改变 GameObject 高度的拍那段才需要关闭这个选项,比如跳起或跳落。

Animator.gravityWeight 是根据烘焙进姿势的Y位置驱动的。当启用时,gravityWeight = 1;当停用时,gravityWeight = 0。gravityWeight 是动画状态转移时用来混合片段的。

基于:类似Root Transform Rotation的方式,你可以从Original 或 Mass Center (Body)选择。还有一个Feet的选项用于动画剪辑修改高度是非常方面的(烘焙姿势被禁用)。当时使用Feet根变换位置Y将匹配所有帧最多的脚Y。因此,混合点始终在Feet周围,当混合或变换时,防止浮动的问题。

偏移:和根旋转变换相似,你可以手动的调整动画剪辑中高的偏移值。

Root Transform Position (XZ) ###

再次,这个(选项)使用了和根旋转变换和根位置变换(Y)相同的概念。烘焙进姿势通常被用于当你希望将 xz 坐标位置偏移强制设定为零的“等待”时。他将会阻止大量计算中的积累误差。这个同样可以根据美工已设定的用来关键帧片段来使用。

Loop Pose 循环姿势 ###

循环姿势(就像是混合树中的混合姿势或是状态转移中的)的产生发生在根变换的定义过程中。一旦根变换被计算完成,这个姿势将会和他相关联。在开始和结束帧之间不同的相关姿势将被计算,而在动画剪辑范围(0-100%)之外的相关姿势将会被创建。

Generic Root Motion and Loop Pose. 一般的根动作和循环姿势 ###

这些从本质上讲和人形根动作相同,但是使用身体变换代替计算/预测根节点中设置的根变换。姿势(所有在根动作骨骼之下的那些骨骼)通过关键根变换被创建。

End.

学习自 58开发网 和 Unity圣典社区


见猎心喜 浅尝辄止 偶有所得 不足为法 & 温故而知新

纸上得来终觉浅 绝知此事要躬行 & 努力奋斗