10 KiB
帧动画角色配置指南(策划版)
本文说明帧动画角色的 Flow 配置与 Yarn 调用。Clip 的切图、导入和帧时长配置不在本文展开。
示例资源:Assets/GameContent/Huoshan/Actor/火山Graph.asset
当前的
火山Graph已有 Clip,但还没有配置 Flow。下文的 Flow 名称是教学示例,不代表资源中已经存在。
1. 先理解 Clip 和 Flow
- Clip:一段独立帧动画,例如
摘帽、扣头切屏特效、伸手表情idle。 - Flow:把多个 Clip 按顺序串成一次完整表演,例如
摘帽 → 伸手表情idle。 - Yarn 调用时,Clip ID 和 Flow ID 的写法完全相同,系统会自动查找对应内容。
适合直接调用 Clip 的情况:只播放一个动作或切换一个循环表情。
适合配置 Flow 的情况:动作需要连续播放多个阶段,并且希望 Yarn 只写一条命令。
2. 打开火山 Graph
- 在 Project 窗口选中
Assets/GameContent/Huoshan/Actor/火山Graph.asset。 - 点击 Inspector 中的 Open Frame Animation Graph Editor。
- 也可以从 Unity 菜单打开:AIBIS > 帧动画 Graph 编辑器,再选择
火山Graph。
编辑器左侧是 Clip / Flow 列表,中间是节点画布,右侧是当前选中内容的属性。
3. 配置一个 Flow
下面以新建 摘帽到伸手_Flow 为例,预期顺序为:
摘帽 → 伸手表情idle(循环)
第一步:把 Clip 放到画布
- 在左侧选择 Clips。
- 把
摘帽从左侧拖到中间画布,生成一个 Node。 - 再把
伸手表情idle拖到画布,生成第二个 Node。
同一个 Clip 可以在画布中生成多个 Node。Node 只是 Flow 中对 Clip 的一次引用,不会复制或修改原 Clip。
第二步:连接播放顺序
从 摘帽 Node 右侧的输出点拖线,连接到 伸手表情idle Node 左侧的输入点。
当前 Flow 只支持单线顺序播放:
- 一个 Node 最多只能连接一个后继 Node;
- 不支持分支;
- 不支持把路径连成环;
- 播放顺序由连线决定,不由节点在画布上的左右位置决定。
第三步:创建 Flow 并指定入口
- 选中
摘帽Node。 - 右键该 Node,选择 Create Flow From Node;也可用画布上方 Canvas > Create Flow From Selection。
- 将 Flow ID 填为
摘帽到伸手_Flow。 - 确认入口是
摘帽Node。入口 Node 会显示 E 标记。
Flow ID 就是 Yarn 中填写的动画名。建议使用有明确含义且不易重复的名称,例如 摘帽到伸手_Flow。
Clip ID 和 Flow ID 共用同一套命名空间,不能重名。修改 ID 后,已有 Yarn 文本不会自动更新,必须同步搜索并修改调用。
第四步:设置结尾行为
选中最后一个 Node,在右侧设置 Override End Behavior。常用选项:
| 选项 | 播放结束后的表现 | 常见用途 |
|---|---|---|
Loop |
从头循环最后一个 Clip | idle、持续表情 |
HoldLastFrame |
停在最后一帧 | 一次动作的定格结尾 |
Clear |
清空当前 Sprite | 动画结束后不显示图片 |
HideTarget |
隐藏渲染目标 | 动画结束后隐藏角色 |
本例最后的 伸手表情idle 应使用 Loop。
注意:只有终点 Node 才能设置结束行为。一个 Node 如果设置了结束行为,就不能再连接后继 Node。中间 Node 播完后会自动进入下一个 Node,不需要设置结束行为。
如需单独调整某个 Node 的速度,可勾选 Override Speed:1 为原速,2 为两倍速,0.5 为半速。速度必须大于 0。
第五步:预览、校验和保存
- 在左侧选择刚创建的 Flow,点击右侧 Focus Flow On Canvas。
- 使用预览区的播放按钮检查顺序和循环结果。
- 点击顶部 Validate,底部 Validation 中不能有 Error。
- 点击顶部 Save 保存。
4. Yarn 调用
初始化角色
帧动画角色首次出现时,先初始化:
<<init_actor 火山 clinic FrameAnimation>>
参数依次为:
角色名 槽位名 角色类型
火山 会加载 Addressable 地址为 FrameAnimation/火山 的 Graph。init_actor 会等待角色 Prefab 和 Graph 加载完成,因此下一行可以直接切动画。
同一段角色出场流程中只需初始化一次,不要在每次换动画前重复初始化。
初始化完成后不会自动播放 Graph 中的 Default Playable,需要再调用一次 Clip 或 Flow。
调用一个 Clip
把 Clip ID 直接写在命令的第一个参数中:
<<change_actor_state 捂头表情idle 火山>>
这条命令会直接播放 火山Graph 中的 捂头表情idle Clip。Clip 播完后的表现由该 Clip 的 End Behavior 决定:
Loop:持续循环,直到被下一次状态切换替换;HoldLastFrame:播放一次并停在最后一帧;Clear:播放一次后清空图片;HideTarget:播放一次后隐藏角色渲染目标。
Clip:播放后立刻继续 Yarn
<<change_actor_state "伸手 石化表情" 火山>>
hs: 我太伤心了。
change_actor_state 只负责开始播放,Yarn 不会等 Clip 播完,会立即执行下一行。适用于:
- 切换 idle 或持续循环表情;
- Clip 需要和对白同时播放;
- 后续时机由策划自己用
wait控制。
Clip:播放完成后再继续 Yarn
<<change_actor_state_async 扣头切屏特效 火山>>
<<change_actor_state 扣头表情idle 火山>>
change_actor_state_async 会等待 Clip:
- 非循环 Clip:等待整段播放结束;
LoopClip:等待第一轮播放结束,然后继续执行 Yarn;动画本身仍会循环。
因此,一次性动作之后要准确切换 idle 时,推荐使用上面的“异步动作 Clip → 循环 idle Clip”写法,不需要猜测 wait 秒数。
调用一个 Flow
Flow 的调用格式与 Clip 完全相同,只需把第一个参数换成 Flow ID。例如已配置 摘帽到伸手_Flow:
Flow:播放后立刻继续 Yarn
<<change_actor_state 摘帽到伸手_Flow 火山>>
hs: 戴上“实实”牌帽子,给你的头顶添件宝!
Yarn 会立即继续对白,Flow 则在后台按照连线依次播放。适合整段表演与对白同时发生的情况。
Flow:播放到终点首轮后再继续 Yarn
<<change_actor_state_async 摘帽到伸手_Flow 火山>>
// Flow 的前置动作和终点 Loop 首轮播放完后,才执行这里
change_actor_state_async 会从入口开始等待整条 Flow:
- 终点为非循环 Clip:等待所有节点自然播放结束;
前置动作 → 终点 Loop的 Flow:等待前置动作和终点 Loop 的第一轮全部结束。
如果终点是 Loop,命令返回后终点 Clip 仍会继续循环,直到被下一次状态切换替换。
快速选择命令
| 要播放的内容 | 希望 Yarn 是否等待 | 写法 |
|---|---|---|
| 单个 Clip | 不等待 | <<change_actor_state ClipID 角色名>> |
| 单个 Clip | 等完整动画;Loop 等第一轮 | <<change_actor_state_async ClipID 角色名>> |
| 一整条 Flow | 不等待 | <<change_actor_state FlowID 角色名>> |
| 一整条 Flow | 等到终点首轮完成 | <<change_actor_state_async FlowID 角色名>> |
命令本身不需要标明目标是 Clip 还是 Flow。系统会用 ID 在当前角色的 Graph 中查找;因此 Clip ID 和 Flow ID 不能重名。
名称中有空格时
Clip ID、Flow ID、角色名或槽位名中包含空格时,必须加英文双引号:
<<change_actor_state "伸手 石化表情" 火山>>
<<change_actor_state_async "摘帽 到 伸手_Flow" 火山>>
不含空格时可以不加;为减少出错,也可以统一加英文双引号。
5. 火山的完整示例
下面同时演示 Clip 和 Flow 调用,并假设已按前文创建 摘帽到伸手_Flow:
<<init_actor 火山 clinic FrameAnimation>>
// 调用 Loop Clip:立即继续 Yarn,idle 在对白期间持续循环
<<change_actor_state 捂头表情idle 火山>>
<<fade_in_actor 火山>>
hs: 医——生——救——我——!
// 调用 Flow:等“摘帽”播完,再等终点“伸手表情idle”完成第一轮
<<change_actor_state_async 摘帽到伸手_Flow 火山>>
// Flow 返回后,终点的伸手 idle 仍在循环
hs: 戴上“实实”牌帽子,给你的头顶添件宝!
// 调用一次性 Clip,并等待它完整播完
<<change_actor_state_async "扣头切屏特效" 火山>>
// 再调用另一个 Loop Clip,替换当前状态并继续对白
<<change_actor_state "扣头表情idle" 火山>>
hs: 我……没有活干了。
6. 提交前检查
- Flow 的入口是否是第一个动作,而不是终点 idle?
- 节点是否按预期连线,且没有分支或环?
- 只有最后一个 Node 设置了结束行为吗?
- 需要持续显示的 idle 是否设置为
Loop? - Flow ID 是否与已有 Clip / Flow 重名?
- Yarn 中的 ID 与 Graph 完全一致,包括空格和大小写吗?
- 需要等动画时是否用了
change_actor_state_async? - 顶部 Validate 是否无 Error?
- 是否点击 Save?
7. 常见问题
调用后没有动画
先检查角色是否用 FrameAnimation 类型初始化,再检查 Graph 的 Addressable 地址是否为 FrameAnimation/角色名。火山应为 FrameAnimation/火山。
提示 playable 找不到
Yarn 中传入的是 Clip ID 或 Flow ID,不是资源文件名、Graph 名或 Node 的 Display Name。检查字符、空格和大小写是否完全一致。
动画刚开始就被打断
后面很可能紧跟了另一条 change_actor_state。普通命令不会等待;需要等当前动画完成时改用 change_actor_state_async。
循环动画导致剧情无法继续
使用 change_actor_state_async 等待 Loop 时,只会等待第一轮,不会无限阻塞。如果仍未继续,先运行 Validate 检查 Flow 路径和结尾配置。
想让 Flow 中途停住
当前 Flow 是顺序播放,不支持分支或中途等待 Yarn。应拆成两个 Clip / Flow,在 Yarn 中分两次调用。