介绍 animation tree 节点在 2D 游戏里面的主要应用场景.
animation tree 是和 animation player 一起使用的, 在 animation player 里面定义好了各种动画, 例如往上下左右四个方向移动. 接下来就是在游戏里面, 怎么控制在什么情况下, 播放哪个动画. 也就是需要用代码实现类似以下的逻辑
如果用户上一次的按键是 W
如果速度是 0, 播放面向上方的静止动画, 否则播放往上移动动画
如果用户上一次的按键是 S
如果速度是 0, 播放面向下方的静止动画, 否则播放往下移动动画
......
可以看出用代码实现这些逻辑比较繁琐, 如果方向不止 4 个, 而是 8 个. 并且再加上 8 个方向的攻击动画, 代码量会更多.
分解问题
首先从一个比较高的抽象层次看上面的逻辑, 动画可以分成三类, 移动, 静止, 攻击. 每类动画, 又有 8 个方向的变种. 玩家每次只能处于一种状态. 方向由玩家上一次的移动方向确定.
AnimationTree 的 StateMachine 部分负责处理 移动, 静止, 攻击状态的转化. BlendSpace2D 负责处理 8 个方向.
StateMachine
有一个开始节点和一个结束节点, 一开始处在开始节点.
在编辑器里面可以加其他的节点, 最简单的是 Animation 节点
鼠标点击节点前面的播放按钮, 就会把状态机的状态设置到这个节点.
下面的进度条会开始走动, 并且开始播放动画
注意, 鼠标需要在 “select and move” 的模式下点击才有效
通过代码控制状态机的状态
在编辑器里面可以通过点击节点前面的播放按钮切换状态机的状态. 在代码里面, 需要先拿到 AnimationTree 对象里面的 parameters/playback. 再通过 playback 的 travel 方法, 转换状态
var state_machine = animation_tree.get("parameters/playback")
state_machine.travel("Left")
travel 里面的参数是节点的名字
需要注意现在还没有在编辑器里面添加节点之间的连线, 在没连线的情况下也是可以直接切换状态的, 不需要节点之间一定有连线.
通过连线做自动转换状态
如果直接用代码操作状态机要转换到哪个状态, 那么和之前直接用 AnimationPlayer 对比, 并没有优势
animation_player.play("Left")
状态机的优势在于可以在编辑器里面设置连线让状态自动转化.
点击 AnimationTree tab 上方的 “Connect nodes” 按钮, 把鼠标切换到添加连线的状态
鼠标在想要连线的两个节点之间拖动, 就可以创建连线
连线有 Switch Mode 和 Mode 两个属性可以设置
switch mode
把鼠标切换到 “select and move” 模式再点击连线, 在右边可以看到 Switch mode
默认是 Immediate 模式, 意思是当切换状态的时候, 如果上一个状态的动画没播放完, 会被马上停止, 直接开始播放下一个动画的开头.
还有另外两个模式是 Sync 模式和 At End 模式. sync 模式表示马上切换到下一个状态的动画, 但是如果上一个动画播放到了第5帧, 那么新状态的动画会在第5帧开始播放.
At End 模式是等待第一个状态的动画播放完了, 才会转化到下一个状态.
mode
Advance 设置里面还有一个 mode
默认是 Enabled, Enabled 和 Disabled 是启用和禁用连线. Auto 是当连线起点的节点播放完后, 会自动跳转到连线终点节点.
BlendSpace
之前用的都是简单的节点, 一个节点就对应一个动画. 还有一些类型的节点可以把多个动画组合起来, 这里先讲 BlendSpace1D 和 BlendSpace2D.
Blend 的意思是把多个动画混合在一起, 如果是 3D 的骨骼动画, 可以做到上半身在招手动作, 下半身做跑步动作之类的混合. 1D 2D 指的是动画的混合需要几个维度的输入信息. 例如要做在走路和跑步直接过度, 如果速度低于 x 时播放走路动画, 速度高于 y 时播放跑步动画, x 和 y 之间播放走路和跑步的结合动画. 就可以用 1D. 因为输入维度只有一个, 就是速度. 而如果想要根据玩家的朝向, 播放不同的动画, 就需要 2D 的输入.
创建 BlendSpace1D 类型的节点, 再点击右边的铅笔按钮, 进入节点的编辑页面.
点击左上角的 Root 可以返回根节点, 也就是刚才状态机的页面.
在 BlendSpace1D 的编辑页面下方, 左下角有 -1, 右下角有 1. 这个是 1D 空间的取值范围.
点击 “Create points” 切换到创建动画点的模式, 在画布中创建 animation
在这个例子中, 我分别在 -0.5 和 0.5 上创建了两个点.
接下来把鼠标模式切换到 “Set the blending position” 模式
如果用鼠标把准星移动到 -0.5 的左边, 那么就会只播放左边的动画
如果把准星移动到 0.5 的右边, 就会只播放右边的动画, 准星在中间的时候, 会播放两个的混合动画.
鼠标模式的右边还有一个 Blend 模式的选项, 可以把默认的实心线段改成 ”- - -”, 即离散模式. 在离散模式里面, 准星距离哪个点最近, 就会直接播放那个点的动画, 没有了中间的混合态.
创建 BlendSpace2D 同理, 变成在 2D 平面上创建点, 准星距离哪个点近, 就会播放哪个点的动画.
在代码中设定 blend 输入值
在编辑器中, 用鼠标移动准星来设置 blend 的输入值, 在代码修改方式是
animation_tree["parameters/BlendSpace1D/blend_position"] = -0.5