> 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`.
* 参与运行时生命周期： **Register → Start → Pause ↔ Resume → Stop**.
* 可以通过 `IModuleContext.ProvideModuleService<T>()`.

向其他模块公开类型化服务。模块系统会自动处理启动顺序——模块按依赖顺序启动，并按相反顺序停止。

### 模块生命周期

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

```mermaid
stateDiagram-v2
    [*] --> Registered : RegisterAsync()
    Registered --> Started : StartAsync()
    Started --> Paused : PauseAsync(reason)
    Paused --> Started : ResumeAsync()
    Started --> Stopped : StopAsync()
    Paused --> Stopped : StopAsync()
    Stopped --> [*]
```

有关完整的生命周期方法契约和实现示例，请参见 [实现自定义模块](/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()`，或 builder  |
| 自定义持久化  | 覆盖 `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" %}
不要通过反射访问内部类型，也不要绕过 builder 来注入依赖。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 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/advanced-topics/extending-the-sdk.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.
