2014年11月6日

动画蓝图

作者 Lina Halper

为何选择动画蓝图?

"动画蓝图“听起来比”蓝图“更高深莫测。 蓝图用起来很有意思,但现在看起来动画蓝图和蓝图的工作原理不太一样,所以我想在此处讨论一下。

首先,让我们谈一下如何在虚幻引擎中播放动画。

我们有两种在SkeletalMeshComponent上播放动画的方法。 您可能已经知道了,SkeletalMeshComponent包含了具有植皮网格物体的骨骼层次结构,可供您播放动画。 如果您拖曳动画到关卡中,它会创建包含SkeletalMeshComponent的SkeletalMeshActor,并为您设置一些基础信息。

Skeletal Mesh Actor

当您选择详细信息面板中的actor时,请您特别注意下图所标出的这部分数据。

UseAnimation

每个SkeletalMeshComponent都具有动画模式设置,我们可以在其中设置我之前谈到过的播放动画的两种方式之一。

  1. Use Animation Asset(使用动画资源): 它将仅被应用于AnimSequence(动画序列)或AnimComposite(动画组合)。 一个资源可以沿着给定的时间轴产生有效的姿势.
  2. Use Animation Blueprint(使用动画蓝图): 这个模式让您可以播放动画蓝图。

第一个选项比较简单,但第二个选项需要一些解释。

第二个选项是Use Animation Blueprint(使用动画蓝图)。


如果您从内容浏览器中拖曳AnimBlueprint(动画蓝图)到关卡视口中,它将会创建如下图显示的具有AnimBlueprint(动画蓝图)设置的SkeletalMeshActor。 (类似于上方的操作,您可以将动画序列拖曳到关卡视口中)

Animation Viewport

播放一个动画比较简单,但播放多个动画并基于不同的情况来混合它们 – 举例来说,播放不同的混合动画 – 这就比较复杂了,所以我们要使用Animation Blueprint(动画蓝图)。 它是基于当前状态来运行的,诸如参数和当前时间等。

如果您创建任意的动画蓝图,您都会看到两个图表,在下方的链接中进行了详细解释。

https://docs.unrealengine.com/latest/INT/Engine/Animation/AnimBlueprints/index.html

它包括了两个图表  - EventGraph(事件图表)和AnimGraph(动画图表)。

事件图表和用于AnimInstance(动画实例)的蓝图相同。 您可以设置变量或调用函数,并且它具有触发的事件。 您可以通过调用每个节点来获得执行的操作序列。

AnimGraph(动画图表)不太一样。 动画在其中进行混合。 您可以把它想象为树形结构,而非操作序列。 每个节点都具有其各自的流程步骤,因此,它会产生姿势。

让我们首先看一下事件图表示例。

Blueprint Diagram

在您了解蓝图后,很容易就能明白。 它会触发这个事件、更新动画,而且在其进行此项操作时,它会设置Speed(速度),并在计算方向后设置Direction(方向)。

那么AnimGraph(动画图表)是如何运作的呢? 它的运行方法不太一样。

AnimGraph At Work

上图中将会播放走路的动画,而它会转到Final Animation Pose(最终动画姿势)。 评估的顺序依然是从左到右,但您更应该把每个节点视作为状态,而非一次性的操作。 当前它只有一个循环的动画。 为让其能继续后期动画,每个节点都必须保存临时数据。 也就是状态值。

当您需要基于[0, 1]间的浮点值来混合两种动画时该如何做呢?

Animation Range

在我们更新动画系统时,它将会执行以下的一系列操作。

  1. 更新EventGraph(事件图表)
  2. 更新AnimGraph(动画图表)
  3. 触发事件

我们要首先更新EventGraph(事件图表),这是因为这样我们可以获得所有最新的变量,这样AnimGraph(动画图表)可以使用这些值来做相应的混合。

这样做不会变更骨骼变换的任何内容。 这个操作实际上是基于时间的变化而更新“state”(状态)。 接下来,我们应何时变更骨骼变换并对帧生成有效姿势? 这个操作在Evaluate(评估)时进行。

在AnimGraph(动画图表)中发生3个事件。

  1. 初始化
  2. 更新
  3. 评估

因为EventGraph(事件图表)不需要评估,所以只发生2个事件。

  1. 初始化
  2. 更新

一般来说,初始化只发生一次,但如果您变更一个“needs reinitialization”(需要重新初始化)的网格物体,初始化可能会再次发生。

更新和评估在每次更新时都会发生。 评估后会产生有效姿势。 我们为什么将这些流程分开? 主要是为了最优化。 评估流程是整个动画处理流程中最消耗系统资源的部分,它会对变换进行大量的数学运算,而且我们可以很方便地对其进行并行计算,因为它不需要与游戏进行任何互动。 另一方面,更新流程具有“Trigger Event”(触发事件) – 诸如AnimNotifies(动画通知),它经常意味着会调用蓝图函数。 这样就需要与游戏的其它部分进行互动,所以要对它并行计算就很难了。

那么能不能改变骨骼变换? 应在什么位置进行此项操作?

看起来大多数人喜欢在蓝图中进行这项操作。 可能在蓝图中进行这种操作更加顺手,但正确的方法是在Animation Blueprint(动画蓝图)中进行此项操作。

由于在动画蓝图中会运算所有的骨骼变换并产生最终结果。 所以如果我们在同一个位置进行这些操作,这样会更好。 如果您在蓝图中进行此操作,根据Ticks(更新)的不同顺序,您可能无法获得最新的骨骼变换。 让我们来考虑一下:

  1. 帧起始
  2. ….
  3. 您的蓝图更新骨骼变换
  4. 动画蓝图被调用 – 更新所有的骨骼变换
  5. ….
  6. 帧结束

这样操作将会让您的变更无效,因为无论您是否修改骨骼变换都不会影响到动画蓝图。 它会运行图表,然后相应地更新变换。 如果我们反向操作则是有效的。

  1. 帧起始
  2. ….
  3. 动画蓝图被调用 – 更新所有的骨骼变换
  4. 您的蓝图更新骨骼变换
  5. ….
  6. 帧结束

但是考虑一下,如果现在还有另一个蓝图也需要变更该如何处理。 这样就变得非常复杂了。

最好的办法是把骨骼变换的操作集中在动画蓝图中进行操作,因为一个实例包含一个动画蓝图。 您可以使用变换节点来修改骨骼变换。

Transform Modify Bone Window

您可以设置您想要修改的变换组件,以及其所处的空间。

Skeletal Control Window

动画蓝图是非常好用的工具。 它提供了许多节点 – 比如,层混合、添加型动画混合、按变量混合、状态、变换等等。 我们在ContentExample项目中准备了Animation.umap文件,您应该看一下。

Content Example

如需了解更多信息,请点击以下链接,并在下方发表您的反馈。

https://docs.unrealengine.com/latest/INT/Engine/Animation/AnimBlueprints/index.html