> For the complete documentation index, see [llms.txt](https://docs.convai.com/api-docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.convai.com/api-docs/zh/cha-jian-yu-ji-cheng/convai-unity-sdk/core-concepts/character-embodiment.md).

# 角色具身化

了解角色的具身化模块如何共享一个组合根、以确定性方式逐帧执行，并且不会对同一根骨骼写入两次。

Convai 角色上的每个具身模块——凝视、身体动画、身体语言、对话流程和情绪——都接入该角色的同一个组合根。这个根负责该角色的 Tick 顺序，也是通往 Animator 和面部的唯一路径。理解这一点，就能解释为什么各模块会协作，而不是争夺同一根骨骼或混合形状。

***

### 组合根

`EmbodimentContext` (`SDK/Runtime/Embodiment/EmbodimentContext.cs`）是组合根：每个角色一个实例。Convai 会在该角色上任何具身模块第一次解析自身时自动添加它——你无需自己添加，它并承载 `[AddComponentMenu("")]` 因此它不会出现在“添加组件”菜单中。

该上下文公开每个模块都会读取的共享基础设施：

| 成员              | 类型                    | 它为模块提供什么                        |
| --------------- | --------------------- | ------------------------------- |
| `CharacterRoot` | `Transform`           | 角色的根变换。                         |
| `EventHub`      | `IEventHub`           | 模块用于监听领域事件的事件总线。                |
| `Logger`        | `ILogger`             | 结构化诊断日志记录。                      |
| `RigBinding`    | `IStandardRigBinding` | 对角色绑定的语义访问——按角色而不是按名称访问骨骼和混合形状。 |
| `Character`     | `ConvaiCharacter`     | 层级中若存在，则为所属角色。                  |

它还会触发三个模块可订阅的事件： `RigBindingChanged` （语义绑定已重建或替换）， `EmbodimentConfigurationChanged` （模块的配置在运行时发生了变化，例如预设切换），以及 `DependenciesPopulated` （仅运行时可用的基础设施，例如 `EventHub` 变得可用）。

每个模块控制器—— `ConvaiGazeController`, `ConvaiBodyAnimationController`, `ConvaiBodyLanguageController`, `ConvaiConversationFlowController`，以及 `ConvaiEmotionController` ——都派生自 `ConvaiCharacterModule<TProfile>` (`SDK/Runtime/Embodiment/ConvaiCharacterModule.cs`），它会在其中解析同一个共享上下文 `OnEnable` 并将该模块注册为其配置文件接收者。无法解析上下文的模块——因为它不在 Convai 角色上——会自我禁用并记录原因，而不是在没有驱动对象的情况下运行。

***

### 自动提供的基础设施

当模块首次需要时，该上下文还会延迟提供另外四个基础设施组件： `StandardRigBinding` （为 Humanoid、ARKit、CC3/CC4 以及其他常见绑定确定哪些骨骼和混合形状承担哪些语义角色）， `AnimatorConductor`, `EmbodimentTickScheduler`，以及 `FacialBlendshapeCompositorHost`）。这四者都是普通组件，你可以在层级中选中并检查它们——SDK 刻意不隐藏它们，因为看不见的组件就无法调试。 `AnimatorConductor`, `EmbodimentTickScheduler`，以及 `FacialBlendshapeCompositorHost` 承载 `[AddComponentMenu("")]`；应将这三者都视为 Convai 提供的行为，绝不要把它们当作你添加的组件或直接调用的 API。

***

### 确定性的 Tick 顺序

每个具有逐帧工作的模块都实现 `IEmbodimentTickable` 并通过以下方式向上下文注册： `RegisterTickable`/`UnregisterTickable` 而不是依赖 Unity 自己的 `Update`/`LateUpdate` 顺序。在 `OnEnable` 并在 `OnDisable` 是受支持的模式；对同一实例重复注册不会产生任何作用。

调度器会让每个可 Tick 对象依次经过三个阶段，且始终按以下顺序：

| 阶段     | 运行内容                                        |
| ------ | ------------------------------------------- |
| `认知`   | 对话流程、凝视和情绪导演会采样信号并更新其读数。                    |
| `表达`   | 凝视、身体和面部执行器将这些读数转换为骨骼、混合形状和 Animator 参数的写入。 |
| `最终定稿` | 面部合成器和 Animator 协调器会在认知和表达都稳定后完成其写入。        |

在同一阶段内，可 Tick 对象的 `TickOrder` 决定谁先运行——数值越小越先运行——若出现并列，则按注册顺序打破平局。这就是为什么 Tick 顺序不取决于层级顺序或哪个模块先启用：重新设置 GameObject 的父级，或以不同顺序添加模块，都不会悄无声息地改变哪个模块会先写入共享骨骼。

***

### 对 Animator 和面部的单写入者访问

两个模块在同一帧写入同一个 Animator 参数或同一个混合形状，这类 bug 只会表现为可见的故障，而不会是编译错误。Convai 通过让 Animator 和角色的面部混合形状各自只有一个写入者来避免这一点：

* `AnimatorConductor` 是 Animator 参数的唯一权威写入者。模块通过协调器提交命名参数写入，而不是调用 `Animator.SetFloat` 直接调用；协调器会记录哪个模块注册了每个参数，并拒绝来自其他模块的冲突注册。
* `FacialBlendshapeCompositorHost` 是面部混合形状的唯一写入者。它会把每个模块的贡献——情绪、LipSync 以及任何自定义层——合成为一组混合形状值，并使用以下区域规则： `ConvaiFacialCompositionProfile` 来决定每个贡献者分别获得口部、眉部、眼部、脸颊和下颌区域的多少。

两者都是自动提供的基础设施，而不是你可以直接配置的组件。如果你需要影响它们写入的内容，请通过拥有该行为的模块来实现——表达由 Emotion 负责，口型由 LipSync 负责——而不是自己在同一个网格上写入混合形状。

{% hint style="info" %}
诸如 Gaze 如何告知 Body Animation 转向之类的跨模块契约属于 `内部` ，属于该包。它们不是公开的扩展点——只有这些组件及其配置文件才是。
{% endhint %}

***

### 五个具身模块

| 模块      | 组件                                 | “添加组件”菜单路径                            | `ModuleIds` 常量                                            |
| ------- | ---------------------------------- | ------------------------------------- | --------------------------------------------------------- |
| Gaze    | `ConvaiGazeController`             | `Convai/Embodiment/Gaze`              | `ModuleIds.Gaze` (`convai.gaze`)                          |
| 身体动画    | `ConvaiBodyAnimationController`    | `Convai/Embodiment/Body Animation`    | `ModuleIds.BodyAnimation` (`convai.body-animation`)       |
| 身体语言    | `ConvaiBodyLanguageController`     | `Convai/Embodiment/Body Language`     | `ModuleIds.BodyLanguage` (`convai.body-language`)         |
| 对话流程    | `ConvaiConversationFlowController` | `Convai/Embodiment/Conversation Flow` | `ModuleIds.ConversationFlow` (`convai.conversation-flow`) |
| Emotion | `ConvaiEmotionController`          | `Convai/Embodiment/Emotion`           | `ModuleIds.Emotion` (`convai.emotion`)                    |

每个 `ModuleIds` (`SDK/Domain/Embodiment/Modules/ModuleIds.cs`）常量是一个路由键，供 `ConvaiEmbodimentPreset` 槽位用它将该模块的设置资源传递给它。五个模块都是可选的，并且彼此独立添加——一个角色可以只运行 Gaze、只运行 Emotion，或任意组合；当某个同伴缺失时，每个模块都会优雅降级。

***

### 下一步

{% content-ref url="/pages/9aa58b1250604b0f44e22f31b27c7ffe4a02efeb" %}
[对话状态](/api-docs/zh/cha-jian-yu-ji-cheng/convai-unity-sdk/core-concepts/dialogue-state.md)
{% endcontent-ref %}

{% content-ref url="/pages/8eaf58d7e1fc1a2176b0c4b26425f595bc8e8851" %}
[资产所有权与写时复制](/api-docs/zh/cha-jian-yu-ji-cheng/convai-unity-sdk/core-concepts/asset-ownership.md)
{% endcontent-ref %}


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.convai.com/api-docs/zh/cha-jian-yu-ji-cheng/convai-unity-sdk/core-concepts/character-embodiment.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
