动画状态机
概览
什么是动画状态机?
「动画状态机」是一种将动画划分为不同“状态”并定义其切换逻辑的架构模式,它广泛应用于游戏开发、人机交互系统与高级 UI 动效设计中,是实现“响应式动画”的核心技术之一。
为什么你需要动画状态机?
传统方式 | 状态机方案 |
时间轴硬编码跳转 | 可视化逻辑图,逻辑清晰易维护 |
需开发介入实现交互 | 设计师独立完成交互动效 |
动画复用困难 | 模块化片段 + 参数化控制,高复用性 |
难以处理复杂状态 | 层级结构 + 混合模式,应对复杂场景 |
使用动画状态机可以非常方便地做互动类型的动画。观看下面的视频,可以直观了解状态机的运行原理及制作方法。
组成要素
一个动画状态机由以下几部分组成:
- 【状态】:简单来说,一个状态就是一段动画。比如将空闲、抽奖、按下、抬起、走路、跳跃等动画分别作为一个状态。
- 【切换条件】:从一个状态切换到另一个状态的条件。切换条件由参数控制。
- 【参数】:作为控制切换的实体。比如设置抬起到按下的切换条件为
pressDown
参数触发;或者设置播放抽中奖品2动画的条件为参数winPrize
被设置为 2。 - 【事件监听】:监听目标元素的鼠标或手势事件,让指定的参数生效。比如监听按钮元素的按下(
pointerdown
)事件,然后触发pressDown
事件,从而驱动状态机的状态流转。
下面分别展开介绍。
基础用法
状态
状态包含开始、动画这 2 种基础类型。
开始状态
表示动画的起始位置,从开始连出的第一个状态即为默认的动画状态。开始到默认状态之间不需要切换条件。
动画状态
一个动画状态由一段动画组成。一段动画由若干个元素的 K 帧组成。在状态的参数设置中可设定以下内容:
- 名称:可自定义修改状态的名称。
- 动画选择:指定当前状态播放的动画。
- 播放速度:当前状态使用的动画的播放速度。
- 循环:当前状态是否循环播放。
切换条件
切换条件以连线的形式存在。连线带有方向性,连线指示了从一个状态流出,然后流入到另一个状态。在连线的参数设置中可以设定以下内容:
- 切换条件:设置可以发生状态切换的参数条件。图中的条件为
pressDown
参数被触发。 - 退出时长:打开退出时长,且时间为 100%,则状态动画播放完成后,自动流入到下一个状态。
- 融合时长:状态切换的动画属性的融合时长,单位为秒。设置融合时长可以避免硬切,可按需使用。
参数
参数有 3 种类型:
- 布尔类型:值为
true
或false
。 - 数字类型:值为数字。
- 触发器类型:没有值,表示一次性触发。与布尔类型相比,使用触发器类型无需手动重置。
切换条件依据选中的参数类型不同,会自动展示不同的输入控件,如下图所示:
转换条件支持复合条件,在同个分组内的条件表示并,不同分组之间表示或。比如下面的切换条件为以下二选一:
- Number1 等于 2 且 Boolean1 等于
true
。 pressDown
触发。
参数需要先在浮动的参数面板中创建:
事件监听
事件监听可以让设计独立完成一个交互而无需开发介入,比如篇首视频中展示的按钮点击交互。
事件在浮动的事件监听面板中创建:
在事件监听的参数设置中可以设定以下内容:
- 目标元素:合成中的元素,目前支持的元素的类型有:图层元素、交互元素、文本元素、形状元素。
- 监听事件:支持的事件有:点击(
click
)、按下(pointerdown
)、抬起(pointerup
)、拖拽移动(pointermove
)。 - 设置参数:目标元素发生监听的事件后,要修改的参数。同样这里的设置参数会根据参数类型展示对应的输入控件。
交互
创建状态机
合成的状态机在合成的参数设置中。状态机以控制器的形式存在。
方式一:通过合成的属性面板
点击画布空白处,可调出合成的参数设置。在下拉底部的输入框中输入状态机名称,点击【+】号,可添加一个控制器资源。
首次创建或切换合成会自动打开相应的状态机面板。若状态机面板被关闭,点击上图的笔图标,可以再次调起状态机面板。
方式二:通过资源管理器
资源管理器切到“动画”标签,然后点击【+】号,点击创建控制器。之后在合成的属性面板的下拉中选中这个控制器(同上一步)。
方式一创建的控制器资源也会展示在资源面板的动画列表中。
(方式一比方式二减少了调起资源面板的过程,看个人喜好)
创建动画
方式一:通过合成的属性面板
在合成属性面板的动画列表属性,点击【+】号创建动画资源。点击选中资源,按回车可重命名,按删除键可删除。
方式二:通过资源管理器
在资源管理器中,点击创建动画菜单,可创建动画资源。
使用动画
方式一:从合成的属性面板中,拖动动画到状态机面板中。
方式二:从资源管理器拖动动画资源到状态机面板中置放
高阶用法
层次状态机
层次状态机是指状态机中可以嵌套状态机,是一种分而治之的思想。举一个例子,角色有待机、行走、跳跃这 3 个状态,在任何状态中一旦触碰到敌人,则会切换到游戏结束状态。如下图所示:
如果没有层次状态机,那么这 3 个状态都需连到游戏结束,如下图所示:
而使用层次状态机,则可以增加一个游戏中的状态机状态,然后将待机、跳跃、行走移到这个状态机中。如下图所示,右键创建一个状态机状态,然后命名为“游戏中”。
双击“游戏中”,进入到这个状态机中,编辑游戏中的状态切换,如下图所示:
这样从“游戏中”切换到“游戏结束”,只需连一条线。只要这条连线的条件满足,就可以切换到游戏结束。
点击底部的导航可以回到对应的层级。
混合
Galacean Effects 提供了业界主流的动画混合模式,以满足不同场景的动效需求:
模式 | 说明 | 应用场景 |
1D(一维混合) | 基于单参数线性插值(如速度值控制走/跑过渡) | 角色运动渐变、进度驱动动画 |
Additive(相加混合) | 在基础动作上叠加额外动画(如边走路边挥手) | 叠加表情、手势微交互 |
Layered(分层混合) | 多层动画独立控制(如上半身攻击 vs 下半身移动) | 复杂角色控制、UI 多维度反馈 |
- 1D:1 维混合是一种此消彼长的关系。
- Additive:可以让 2 个动画或状态机进行属性值相加混合。
- Layered:分层即为各层合并的意思,是最常用的一种混合方式,比如 3 个动画合并为一个状态,其中有的动画有循环,有的动画没有循环,或者循环的时间不一样。
1 维混合
通过右键菜单,创建一个动画混合状态,如下图所示:
在参数面板创建一个数字类型的参数,如下图所示:
然后在混合状态的属性面板中选中这个参数,并添加 2 个动画,一个是向上走,一个是向右走。
那么当 weight
等于 0 时,元素就会向上走。当 weight
等于 1 时,元素就会向右走。当 weight
偏向于 0 时,元素的行走角度会越偏向于垂直;当 weight
偏向于 1 时,元素的行走角度会越偏向于水平。该参数对元素的所有属性生效。
一个实际使用场景是控制角色的走路幅度。将角色的走路与跑步进行混合,然后用一个参数控制。当参数越靠近 1 时,就会走得越快。这样就可以通过一个参数来控制角色的走路快慢(配合位移)。
使用混合树,可以让状态机进行混合。首先创建一个混合树状态,如下图所示:
双击混合树状态进入编辑,如下图所示:
混合树同样通过一个权重参数控制混合效果。图中的 A 表示 0 端,B 表示 1 端。
我们让状态机状态与动画进行混合。混合树还可以嵌套混合树,形成级联的树形结构,如下图所示:
点击底部的导航可以回到对应的层级:
相加混合
相加混合的常用场景是混合不同元素的属性,或混合同一个元素的不同属性。让它们可以一起播放。相加混合的参数作用在第 2 个动画上,默认值为 1。
分层混合
分层混合可以将不同元素的属性或者同元素的不同属性进行合并。比如在以上例子中,当按下参数触发时,状态机从待机切到一个分层混合状态。这个状态由 3 个动画组成,其中前 2 个动画循环,后 1 个动画不循环。那么这个混合状态就合并了这 3 个动画的效果。
如果是同元素同属性,则后面的动画会覆盖前面的。制作时,如果出现混合中的动画不生效时,请检查是否在前面的动画中出现同元素同属性的情况。
模型元素的状态机
支持给模型的 TreeItem
元素添加状态机。在 TreeItem
的属性面板中添加状态机,如下图所示:
所有的制作方法都与上面描述的相同。合成的动画是在编辑器生产的,而模型的动画是导入进来的。所以动画需要从资源面板中拖到状态机面板中。
状态机的能力边界
状态机的适用场景存在以下限制:
- 仅适用于状态可枚举的场景。对于连续变化的场景则不适用,比较温度计的液体高度是连续变化的。如果能将连续的简化为离散数字,则可使用状态机。比如将温度计的液体高度变为 5 格。
- 状态之间的平滑衔接可能会受到限制。通过设置融合时间可以解决一部分问题。但有一些场景可能无法通过融合时间解决,需要通过编程解决或直接硬切。比如动画一旋转的角度从 0 转到 1440,切换到动画二是从 0 转到 360,如果切换到动画二设定融合时间,那么就会出现倒着转回去的情况。
- 状态可枚举,但过多,且两两个状态之间都可互相切换。如果有 n 个状态,总共就会有 (n - 1) + (n - 2)…+1 条连线。连线密密麻麻的,状态机就会变得难以维护。所以这种情况编程实现(状态机)可能是更优解。
开发控制状态机
开发可以控制参数,驱动状态机流转,其效果类似于在播放过程中在参数面板实时修改参数。
比如开发可以在请求之后,得到中奖奖品,然后设置状态机参数 winPrize
,进而让状态机切换到相应的状态。开发者使用文档见:状态机开发者文档。