动画树

简介

使用:参考:动画播放器 <类_动画播放器>,Godot的动画系统,是你能在任何游戏引擎中找到最为灵活的系统。可以在任何节点或资源中对任何属性进行动画处理,以及专门的变换,贝塞尔,函数调用,音频和子动画轨道,该动画系统相当独特。

然而,通过“动画播放器”混合这些动画的支持相对有限,只能设置固定的交叉渐变过渡时间。

AnimationTree is a new node introduced in Godot 3.1 to deal with advanced transitions. It supersedes the ancient AnimationTreePlayer, while adding a huge amount of features and flexibility.

创建动画树

首先,必须明确“动画树”节点不包含它自己的动画。相反,它使用包含在“动画播放器”节点中的动画。通过这种形式,您可以像往常一样编辑动画(或从3D场景导入动画),然后使用这个额外节点来控制播放。

在3D场景中经常使用“动画树”。当从3D交换格式导入场景时,它们通常自带动画(要么是多个,要么是在导入时从一个大的动画中拆分出来)。最后,导入的Godot场景在“动画播放器”节点中包含动画。

很少在Godot中直接使用导入的场景(它们要么实例化,要么来自继承),您可以将“动画树”节点放置在包含导入的新场景中。然后,将“动画树”节点指向导入场景内创建的“动画播放器”节点。

这是在“第三人称射击游戏演示”<https://github.com/godotengine/tps-demo>中的设置,参考下图:

../../_images/animtree1.png

为玩家创建了一个以“动力学物体”为根节点的新场景。在这个场景中,已实例化原来的“.dae”(Collada)文件,并创建“动画树”节点。

创建树

可以在“动画树”中使用三种主要节点类型:

  1. 动画节点,从链接的“动画树”中引用动画。
  2. 动画根节点,用于混合子节点。
  3. 动画混合节点,它们在“动画节点混合树”中使用,通过多个输入端口作为单图混合。

在“动画树”中设置根节点,如下几种类型可供选择:

../../_images/animtree2.png
  • “动画节点动画”:从列表中选择一个动画并播放它。这是最简单的根节点,一般不直接用作根节点。
  • “动画节点混合树”:包含许多*混合*类型的节点,如调配, 混合2, 混合3, 一对一等。这是最常用的根节点之一。
  • “动画节点状态机”:将多个根节点作为图中的子节点。每个节点作为一个*状态*使用,并提供多个函数在状态之间进行切换。
  • “动画节点二维混合空间”:允许在二维混合空间中放置根节点。在二维中控制混合位置以混合多个动画。
  • “动画节点一维混合空间”:以上的简化版本(一维)。

混合树

一个“动画节点混合树”可包含用于混合的根节点和常规节点。节点从菜单添加到图中:

../../_images/animtree3.png

所有混合树默认包含一个“输出”节点,为了让动画播放,必须有个东西与其相连。

测试此功能最简单的方法是直接连接一个“动画”节点:

../../_images/animtree4.png

这会简单地回放动画。确保“动画树”节点对实际发生的事情是激活的。

以下是可用节点的简短描述:

混合2/混合3

这些节点将通过用户指定输入的两个或三个混合值之间进行混合:

../../_images/animtree5.gif

对于更复杂的混合,建议使用混合空间。

混合也可以使用过滤器,也就是说,您可以单独控制通过混合功能的轨道。这对于动画的层叠非常有用。

../../_images/animtree6.png

OneShot

此节点将执行子动画,并在完成后返回。可以用于定制淡入淡出时间,以及过滤器。

../../_images/animtree6b.gif

查找

此节点可用于执行对图中任何子节点的查找命令。设置时间后,该值返回-1。

时间缩放

允许缩放任何子节点的动画速度(或将其反转)。设置为0会暂停动画。

转换

非常简单的状态机(当您不想使用“状态机”节点时)。动画可以连接到输出,并且可以指定转换时间。

二维混合空间

“二维混合空间”是在二维空间中进行高级混合的节点。在二维空间内添加点,然后控制位置来确定混合:

../../_images/animtree7.gif

可以控制X和Y的范围(为方便起见,还可以标记它们)。默认情况下,可以在任何位置放置点(只需右键单击坐标系统或使用*添加点*按钮)将自动生成德洛内三角形。

../../_images/animtree8.gif

也可以通过禁用*自动三角形*选项来手动绘制三角形,虽然基本上没必要这么做:

../../_images/animtree9.png

最后,可能会更改混合模式。默认情况下,混合是通过在最近的三角形内插点来实现的。当处理二维动画(逐帧)时,您可能希望切换到*离散*模式。此外,如果您想在离散动画之间切换时保持当前播放位置,请使用*进位*模式。此模式可在*混合*菜单中更改:

../../_images/animtree10.png

一维混合空间

这类似于二维混合空间,但在一维空间中(所以不需要三角形)。

状态机

这个节点是个相对简单的状态机。根节点可以创建并通过线路连接。状态通过*转换*连接,它们是具有特殊性质的连接。转换是单向的,但是可以用两种方式连接。

../../_images/animtree11.gif

有多种类型的转换:

../../_images/animtree12.png
  • Immediate: Will switch to the next state immediately. The current state will end and blend into the beginning of the new one.
  • 同步:立即切换到下一个状态,但会将新状态搜索并放置到旧状态的回放位置。
  • 末尾:将等待当前状态回放结束,然后切换到下一个状态的开始动画。

转换也有一些属性。点击任何转换,它会显示在属性面板中:

../../_images/animtree13.png
  • *切换模式*为过渡类型(见上文),可以在此处创建后修改。
  • *自动前进*当达到此状态时将自动开启转换。最适合“末尾”切换模式。
  • *前进条件*设置此条件后,将打开自动前进。这是一个可以用变量名填充的自定义文本字段。可以从代码中修改变量(稍后将对此进行详细介绍)。
  • *X消隐时间*是在这个状态和下一个状态之间交替渐变的时间。
  • *优先*与代码中的“travel()”函数一起使用(后面会详细介绍)。当从一种状态移动到另一种状态时,赋予这个节点更高的优先级。
  • *禁用*允许禁用此转换(它不会在行程或自动前进期间使用)。

根骨骼运动

当处理3D动画时,一种流行的技术是动画师利用根骨骼为其余部分骨骼制作运动动画。这使得动画角色的脚步与下面的地板相匹配。并且允许在电影拍摄期间与物体进行精确的交互。

在Godot中回放动画时,可以选择这根单根骨作为*根运动轨迹*。这会在视觉上取消单根骨的转换(动画将保持原状)。

../../_images/animtree14.png

然后,实际运动可以通过:参考:`动画树<类_动画树>`API作为转换:

anim_tree.get_root_motion_transform()
animTree.GetRootMotionTransform();

可以提供给诸如:参考:`动力学物体.移动和滑动<类_动力学物体_方法_移动和滑动>`这样的函数来控制角色移动。

还有一个名为“根骨骼运动视图”的工具节点,可以放置在场景中,并作为你的角色和动画的自定义地板(此节点通常在游戏期间禁用)。

../../_images/animtree15.gif

使用代码控制

创建树和预览之后,只剩下一个问题:“如何使用代码控制所有的节点?”。

请记住动画节点只是资源,因此,它们之间共享所有实例。节点中的设定值会直接影响使用此“动画树”场景的所有实例。有一些很酷的用例,例如你可以复制、粘贴你的动画树部分,或在不同的动画树中重用具有复杂布局(例如状态机或混合空间)的节点。

实际的动画数据包含在“动画树”节点中,并通过属性访问。检查“动画树”节点的“参数”部分,查看所有可以实时修改的参数:

../../_images/animtree16.png

这很方便,因为它可以通过“动画播放器”获得动画效果,甚至是“动画树”本身,允许实现非常复杂的动画逻辑。

想要通过代码修改这些值,必须获得该属性的路径。这是很容易做到的,把鼠标悬停在任何参数:

../../_images/animtree17.png

允许设置或读取它们:

anim_tree.set("parameters/eye_blend/blend_amount", 1.0)
# Simpler alternative form:
anim_tree["parameters/eye_blend/blend_amount"] = 1.0
animTree.Set("parameters/eye_blend/blend_amount", 1.0);

状态机行程

执行“状态机“的行程能力,是Godot引擎的优秀特性之一。可以指示图表从当前状态转到另一个状态,我们可以访问其所有的中间状态。这是通过A*算法实现的。

要使用行程能力,您应该首先从“动画树”节点中检索:参考:`动画节点状态机回放<类_动画节点状态机回放>`对象(导出为一个属性)。

var state_machine = anim_tree["parameters/StateMachine/playback"]
AnimationNodeStateMachinePlayback stateMachine = (AnimationNodeStateMachinePlayback)animTree.Get("parameters/StateMachine/playback");

一旦检索到,可以调用它提供的许多函数之一:

state_machine.travel("SomeState")
stateMachine.Travel("SomeState")