具身化如何工作
了解 Convai 如何在运行时构建每个角色的具身化基础设施,以及各模块每帧运行的固定顺序。
角色携带的每个具身化模块都在每个角色上共享一个运行时对象,Convai 还会在每一帧按固定顺序运行这些模块,因此两个模块永远不会以冲突的方式写入同一根骨骼或 blendshape。本页描述运行时会发生什么:角色开始运行时层级里会出现什么、模块按什么顺序 tick,以及为什么对 Animator 和面部的写入不会冲突。关于这些机制背后的 composition-root 模型,请参见 角色 Embodiment.
角色开始运行时层级中会出现什么
某个角色上第一个完成解析的具身化模块会创建一个 EmbodimentContext 它会悄悄地在该角色的根节点上创建。你无需手动添加它——它携带 [AddComponentMenu("")],因此它不会出现在 Add Component 菜单中——但一旦创建,它就是一个普通组件:在层级中选中它,就可以检查它解析出了什么。
随后,context 会在模块首次需要每一部分基础设施时为模块提供这些共享内容:
StandardRigBinding
为 Humanoid、ARKit、CC3/CC4 以及其他常见骨架,解析哪些骨骼和 blendshape 分别承担哪些语义角色——头部、脊柱、张嘴等其余部分。
在 Add Component 菜单中显示为 Convai > 具身化 > Character Rig,但当某个模块第一次需要骨架数据时,Convai 会替你添加它。
AnimatorConductor
Animator 参数的唯一写入者;模块通过它提交带名称的参数写入,而不是直接调用 Animator.SetFloat 。
隐藏([AddComponentMenu("")])——Convai 会替你添加它。
EmbodimentTickScheduler
按照下面描述的 tick 顺序运行所有已注册模块。
隐藏([AddComponentMenu("")])——Convai 会替你添加它。
FacialBlendshapeCompositorHost
面部 blendshape 的唯一写入者;把每个模块的贡献合成为一组数值。
隐藏([AddComponentMenu("")])——Convai 会替你添加它。
Convai 故意不把这些组件从层级中隐藏起来,即使是那些未出现在 Add Component 菜单中的组件也一样:一个你无法选择和检查的组件,在角色行为看起来不对时就无法调试。
模块在每一帧中的运行顺序
需要逐帧工作的模块会在 context 中注册为一个 IEmbodimentTickable 而不是依赖 Unity 自身的 Update 顺序。调度器会让每个已注册的 tickable 依次经过三个阶段,而且始终按这个顺序: 认知,然后 表情,然后 Finalize.
实际中,这意味着 Conversation Flow、Gaze 和 Emotion 会在 认知期间采样输入并更新各自的读数,然后在任何模块向骨架写入之前完成。等到 Gaze 或 Body Animation 的 actuator 在 表情中运行时,它读取到的对话状态已经是该帧的最新状态——而不是落后一帧。 Finalize 最后运行,这样面部 compositor 和 Animator conductor 只有在每个模块都有机会贡献之后才应用它们的写入。
在同一阶段内,模块通过一个 TickOrder 值——数值越小越先运行——而不是依赖它在层级中的位置或何时启用。重新设定一个 GameObject 的父级,或者以不同顺序添加模块,都不会改变哪个模块先写入共享骨骼。
为什么两个模块永远不会争抢同一个 blendshape
两个模块在同一帧里写入同一个 Animator 参数或同一个面部 blendshape,是一种会表现为可见故障而不是编译错误的 bug。Convai 通过让 Animator 和面部各自只有一个写入者来避免这种情况—— AnimatorConductor 以及 FacialBlendshapeCompositorHost ——上表中的
模块绝不会直接写入 Animator.SetFloat 或 blendshape 值。它会把自己的意图提交给 conductor 或 compositor,而 conductor 会拒绝第二个模块对另一个模块已拥有参数的注册。compositor 会使用一个 ConvaiFacialCompositionProfile中的区域规则,来解决同一面部区域上的重叠请求——角色说话时,Emotion 和 LipSync 都会关注嘴部——而不是让最后写入的模块悄悄获胜。
当某些地方看起来不对时该看哪里
打开 Convai > 具身编辑器 要直接查看这个运行时视图,请看 设置 标签页会报告每个模块解析出了什么,而 Live 标签页在 Play 模式下会显示角色当前的对话状态和情绪分数。
最后更新于
这有帮助吗?