> 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 和面部的唯一路径。理解这一点就能解释为什么各模块会协作，而不是争夺同一根骨骼或 blendshape。

***

### 组合根

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

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

| 成员              | 类型                    | 它为模块提供什么                                |
| --------------- | --------------------- | --------------------------------------- |
| `CharacterRoot` | `Transform`           | 角色的根变换。                                 |
| `EventHub`      | `IEventHub`           | 模块用于监听领域事件的事件总线。                        |
| `日志记录器`         | `ILogger`             | 结构化诊断日志记录。                              |
| `RigBinding`    | `IStandardRigBinding` | 对角色骨架的语义化访问——按角色而不是按名称访问骨骼和 blendshape。 |
| `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 及其他常见骨架确定哪些骨骼和 blendshape 扮演哪些语义角色）， `AnimatorConductor`, `EmbodimentTickScheduler`，以及 `FacialBlendshapeCompositorHost`。这四个都是普通组件，你可以在层级视图中选中并检查它们——SDK 刻意不隐藏它们，因为看不见的组件就无法调试。 `AnimatorConductor`, `EmbodimentTickScheduler`，以及 `FacialBlendshapeCompositorHost` 携带 `[AddComponentMenu("")]`；请将这三者都视为 Convai 提供的行为，绝不要把它们当作你添加的组件或直接调用的 API。

***

### 确定性的 tick 顺序

每个具有逐帧工作的模块都会实现 `IEmbodimentTickable` 并通过 `RegisterTickable`/`UnregisterTickable` 而不是依赖 Unity 自身的 `Update`/`LateUpdate` 顺序向上下文注册。 `OnEnable` 中以及 `OnDisable` 中注销，是受支持的模式；同一实例注册两次不会产生任何效果。

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

| Phase      | 运行内容                                                 |
| ---------- | ---------------------------------------------------- |
| `认知`       | 对话流程、注视和情绪导演会采样信号并更新其读数。                             |
| `表情`       | 注视、身体和面部执行器会将这些读数转换为对骨骼、blendshape 和 Animator 参数的写入。 |
| `Finalize` | 在认知和表情都稳定后，面部合成器和 Animator 指挥器会完成它们的写入。              |

在同一阶段内，一个可 tick 对象的 `TickOrder` 优先级决定谁先运行——数值越小越早——若相同则按注册顺序决定。这就是 tick 顺序不依赖层级顺序或哪个模块先启用的原因：重设 GameObject 的父子关系，或者以不同顺序添加模块，都不会悄无声息地改变哪个模块先写入共享骨骼。

***

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

两个模块在同一帧写入同一个 Animator 参数或同一个 blendshape 的 bug，通常只会表现为可见的卡顿/异常，而不会导致编译错误。Convai 通过让 Animator 和角色的面部 blendshape 各自只有一个写入者来避免这一点：

* `AnimatorConductor` 是 Animator 参数的唯一权威写入者。模块通过指挥器提交带名称的参数写入，而不是调用 `Animator.SetFloat` ；指挥器会记录每个参数由哪个模块注册，并拒绝来自其他模块的冲突注册。
* `FacialBlendshapeCompositorHost` 是面部 blendshape 的唯一写入者。它会将每个模块的贡献——情绪、唇同步以及任何自定义层——合成为一组 blendshape 值，并使用 `ConvaiFacialCompositionProfile` 中的区域规则来决定每个贡献者能分到多少嘴部、眉部、眼部、脸颊和下颌区域。

二者都是自动提供的基础设施，而不是你直接配置的组件。如果你需要影响它们写入的内容，请通过拥有该行为的模块来做——表情用 Emotion，嘴型用 LipSync——而不是自己直接在同一个网格上写 blendshape。

{% hint style="info" %}
跨模块契约，例如注视如何告诉身体动画转身， `internal` 包内部的。它们不是对外公开的扩展点——公开的只有这些组件及其配置文件。
{% endhint %}

***

### 这五个具身模块

| 模块   | 组件                                 | “添加组件”菜单路径                            | `ModuleIds` 常量                                            |
| ---- | ---------------------------------- | ------------------------------------- | --------------------------------------------------------- |
| 注视   | `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`) |
| 情绪   | `ConvaiEmotionController`          | `Convai/Embodiment/Emotion`           | `ModuleIds.Emotion` (`convai.emotion`)                    |

每个 `ModuleIds` (`SDK/Domain/Embodiment/Modules/ModuleIds.cs`）常量是 slot 使用的路由键，用于把该模块的设置资源交给它。 `ConvaiEmbodimentPreset` slot 用来把该模块的设置资源交给它。五个模块都是可选的，且可独立添加——角色可以只运行 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 dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

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

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

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.
