Blend Tree
动画树最原始的这个 idea,至少老师个人的理解,是从表达式树开始的。
动画树其实是一个单向展开的树,并不是一个图,它最终一定要有一个流出的节点。就像表达式树一样,最终有一个根节点。
LERP Blend Node
最常用的就是线性插值节点。
动画树的线性插值节点中,最简单的是二元线性插值,输入的是个权重。比如说输入权重 0 就表示用 clips A,1 就表示全部选用 clip B,0.5 的话就两个 clip 各取一半。
如果是三通道或是四通道的线性插值系统,一般会单独输入权重,也就是 weight 1、weight 2、weight 3,让我们自己来控制。
Additive Blend Node
Additive Blending 在动画树里面也有专门的节点。
Express Layered ASM in Blend Tree
Use a blend tree to describe the desired final pose of ASMs
前面讲的 Layered ASM 就可以很轻松地用这样的结构的动画数据表达出来。
因此动画树可以认为是 Layered ASM 的一个超集,它可以表达所有的Layered ASM 能表达的东西。
Blend Tree Nodes
动画树真正的酷的地方就在于它是一个递归结构。38:17
虚幻引擎在动画树的节点设计得非常的灵活,节点既可以是一个动画的素材,也可以是一个 Blend Space,也可以是一个 ASM,最终只输出一个节点即可。
虚幻引擎中,ASM 动画状态机节点点开了之后,它里面又可以内嵌很多的 node,这些 node 又可以再内嵌一棵小动画树。
这小节提到的都是叶节点,叶节点往上有很多中间的计算节点,最常见的就是前面讲的各种 LERP 节点、Additive Blend 节点或是 Mask 节点。
Unreal Animation Blueprint
A blueprint graph which outputs a final pose
- Take clip poses or the results of ASMs as input
- Blend input poses by different methods
虚幻引擎中的节点可以如上图连接。
动画树为什么可以一直变换它的输出?树的数据是静态的,它为什么可以根据鼠标键盘、游戏的状态等输入,从而产生不同的 pose? 这里面有一个关键的东西就是动画树的控制变量。
Blend Tree Control Parameters
动画树中,我们会定义大量的变量暴露给外面的 gameplay 系统。比如说当前的移动速度、朝向、健康状态、是否跳跃、是否受到攻击等。可以想象动画树是无数个流着水的管道,每个管道汇在一起,由阀门控制用哪个管道多一点,而这个阀门就是由控制变量来控制的。
Unreal Animation Blueprint Control
游戏引擎一般会定义变量叫 variable。variable 有两类:
- 环境的一些参数
- 比如我的速度,我的朝向,我的健康值。
- 比如说现在血量只有一半了,那角色动作会切换到很虚弱的动作,这种动画提前做好。如果血量很满,那这时候就可能是另外一组昂首挺胸走路的动作。两组动作在开关处混合,开关取决于血量是不是大于 50%。
- event
- 当一件事情(事件)发生的时候,会修改一些变量。这个修改一般是 event 发生的时候,把动画树里面的一些局部的标记给修改掉。
- 比如现在手上拿了一把步枪,突然接到一个指令,要把步枪换成一颗火箭筒。这个时候角色拿枪的上半身的动画就会从一个动作变成了另一个动作,变成扛住火箭筒。也就是说这个信号来了,就会修改动画树内部的一些状态。
相当于类的 private 的(私有的)变量,但是它可以被外部的状态激活并且修改。
我们知道了动画会像流水一样被阀门控制如何混合,另外动画树中还有很大的一块代码是计算结构,去计算每个阀门开放的百分比。这些百分比通过变量控制,外部的控制信号在动画树中进行一些简单的加减乘除比较。
相当于上面文档中最后的“条件”部分。
现在做引擎如果觉得太复杂,可以定义一些接口的变量。可以让我们的 gameplay 系统可以去修改这些变量。在动画系统做好之后,让它在每个节点读取这些变量。然后允许它支持一些简单的比如加减乘除、比较大小或等于的运算,这样也可以实现一个有点意思的动画系统。