> 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/advanced-topics/extending-the-sdk.md).

# 运行时模块系统

了解 Convai 运行时模块系统，包括何时使用自定义模块、模块生命周期状态，以及哪些 SDK 扩展点可以安全使用。

Convai Unity SDK 基于一个模块系统构建，该系统为可选功能——唇形同步、情感、视觉、叙事设计——在运行时生命周期中提供了明确的位置。你可以使用同一系统添加自己的模块：它们会接收相同的启动序列、访问相同的服务，并可与其他模块共享接口。

### 你需要自定义模块吗？

当你需要以下行为时，自定义模块是合适的工具：

* **参与 SDK 运行时生命周期** ——与 SDK 一起启动和停止，而不是独立运行
* **与其他 SDK 模块共享服务** ——例如，公开一个 `IAudioAnalysisService` 供情感模块或你自己的代码使用
* **响应 SDK 域事件** ——角色语音状态、情感变化、动作触发
* **集成硬件或平台系统** ——触觉设备、生物识别传感器、计分引擎

以下情况不需要自定义模块：

* 在 MonoBehaviour 中响应 SDK 事件——直接通过 `context.Events` 从一个 `IInjectable` 组件，或者使用上的公共事件 `ConvaiCharacter`
* 角色上的简单自定义行为——向角色的 GameObject 添加一个 MonoBehaviour
* 从你自己的脚本调用 Convai REST API——使用 `ConvaiManager.ActiveManager` 直接

如果不确定，先从一个 `MonoBehaviour` 开始，只在需要生命周期集成时再升级到 `IConvaiModule` 。

### 什么是模块

模块是一个实现 `IConvaiModule`的类。它：

* 具有稳定的 `ModuleId` 字符串（按约定应唯一、小写、以连字符分隔——例如， `"my-company.haptic-feedback"`).
* 通过 `RequiredModules` 声明对其他模块的依赖，以及通过 `RequiredServices`.
* 参与运行时生命周期： **注册 → 启动 → 暂停 ↔ 恢复 → 停止**.
* 可通过 `IModuleContext.ProvideModuleService<T>()`.

模块系统会自动处理启动顺序——模块按依赖顺序启动，并按相反顺序停止。

### 模块生命周期

生命周期有五个状态。 `RegisterAsync` 在任何 `StartAsync` 调用之前先对所有模块运行，为每个模块在任何模块开始主动处理之前提供一个保证的服务注册窗口。

```mermaid
stateDiagram-v2
    [*] --> 已注册：RegisterAsync()
    已注册 --> 已启动：StartAsync()
    已启动 --> 已暂停：PauseAsync(reason)
    已暂停 --> 已启动：ResumeAsync()
    已启动 --> 已停止：StopAsync()
    已暂停 --> 已停止：StopAsync()
    已停止 --> [*]
```

有关完整的生命周期方法契约和实现示例，请参见 [实现自定义模块](/api-docs/zh/cha-jian-yu-ji-cheng/convai-unity-sdk/advanced-topics/implement-a-custom-module.md).

### 安全的扩展点和内部 API

仅使用下面列出的公共扩展点。内部类型和特定平台层可能会在不通知的情况下更改。

#### 安全的扩展点

| 什么      | 方法                                                                     |
| ------- | ---------------------------------------------------------------------- |
| 自定义模块行为 | 实现 `IConvaiModule` 并通过以下方式注册 `RegisterModule()` 或 `AddModule()`        |
| 模块间服务   | `ProvideModuleService<T>()` / `TryGetModuleService<T>()`               |
| 自定义凭据   | 重写 `CreateRuntimeBuilder()` 并调用 `builder.UseConfig()`                  |
| 自定义身份   | `SetEndUserIdentityProvider()` / `SetEndUserMetadataProvider()`，或者生成器  |
| 自定义持久化  | 重写 `CreateRuntimeBuilder()` 并调用 `builder.UsePersistence()`             |
| 字符级组件集成 | 实现 `IInjectable<IConvaiCharacterDependencies>` 在角色层级中的 MonoBehaviour 上 |
| 事件订阅    | `IEventHub.Subscribe<T>()` / `Unsubscribe<T>()`                        |
| 日志路由    | `ConvaiLogger.RegisterSink(ILogSink)`                                  |

#### 内部 API —— 请勿重写

| 区域                           | 为什么                                |
| ---------------------------- | ---------------------------------- |
| `ConvaiRuntime` 内部实现         | 设计上为私有；如有更改，恕不另行通知                 |
| 传输层（`ITransportProvider` 实现） | 特定于平台；重写会破坏平台支持                    |
| RTVI 协议处理器（`RTVIHandler`)    | 序列化格式与 Convai 的后端绑定——任何覆盖都会使协议失去同步 |
| `ConvaiRoomManager` 内部实现     | 房间协调器内部不是扩展点                       |
| 超出 `RequiredModules`         | 拓扑排序是自动的；不要依赖注册顺序                  |

{% hint style="warning" %}
不要对内部类型使用反射，也不要绕过构建器来注入依赖。SDK 内部在不同版本之间会变化——绕过公共 API 的代码在升级后会在没有警告的情况下失效。
{% endhint %}

### 下一步

{% content-ref url="/pages/c94f3576730a705ef8d7adec01d712a12612b542" %}
[实现自定义模块](/api-docs/zh/cha-jian-yu-ji-cheng/convai-unity-sdk/advanced-topics/implement-a-custom-module.md)
{% endcontent-ref %}

{% content-ref url="/pages/0bd691fc4d8a06b0dbafd0f28b11f39be6f57f9a" %}
[事件系统](/api-docs/zh/cha-jian-yu-ji-cheng/convai-unity-sdk/core-concepts/event-system.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/advanced-topics/extending-the-sdk.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.
