> 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/web-plugins/convai-embody/add-a-3d-character-to-a-three-js-scene.md).

# 向 three.js 场景添加 3D 角色

使用无需框架的 Convai Embody API，将 Convai 角色添加到现有的 3D 网页场景中，并在你自己的渲染循环中更新它。

将 Convai 角色添加到您已经渲染的 three.js 场景中，无需 React。当您的应用负责渲染器、场景和相机时，请使用此页面。最终，角色会出现在您的场景中，并通过您的渲染循环驱动进行口型同步说话。

### 前置条件

* 一个带有渲染器、带灯光的场景、相机和渲染循环的 three.js 应用。
* Node.js 18 或更高版本，以及一个打包工具。
* Convai API 密钥或认证令牌，以及角色 ID。角色的 avatar 需要一个已发布的 web body，或者必须为其应用默认 body。

### 安装这些包

的根入口点 `@convai/embody` 不导入 React 也不导入 `@react-three/fiber`，因此此路径只需要这两个必需的同级依赖。

```bash
npm install @convai/embody @convai/web-sdk three
```

### 创建角色

`createCharacter` 会解析角色的 body，加载它，打开 Convai Web SDK 连接，并返回一个句柄。将该句柄的 `root` 添加到场景中，并将你的相机传给它，这样角色的视线就能跟踪相机。

{% code title="src/character.ts" %}

```typescript
import * as THREE from 'three'
import { createCharacter } from '@convai/embody'

export async function addCharacter(
  scene: THREE.Scene,
  camera: THREE.Camera,
  renderer: THREE.WebGLRenderer,
  token: string,
) {
  const character = await createCharacter({ token, characterId: 'YOUR_CHARACTER_ID' })

  scene.add(character.root)
  character.camera = camera

  const clock = new THREE.Clock()
  renderer.setAnimationLoop(() => {
    character.update(clock.getDelta())
    renderer.render(scene, camera)
  })

  return character
}
```

{% endcode %}

`update` 使用经过的秒数推进动画、口型同步、视线、呼吸和眨眼。每帧调用一次，在渲染之前。

{% hint style="warning" %}
没有 `character.camera`，视线跟踪不会起作用，角色会直视前方。等相机存在后再设置它。
{% endhint %}

### 向角色发送消息

`character.client` 是 Convai Web SDK `ConvaiClient` 由 Convai Embody 打开的。将它用于对话。仅在角色创建时 `null` 仅当角色是使用 `connect: false`.

```typescript
character.client?.sendUserTextMessage('Walk me through the lockout procedure.')
```

### 释放角色

调用 `dispose` 当角色离开页面时调用。它会释放模型、材质和纹理以及动画混合器，并关闭 Convai Embody 打开的连接。

```typescript
scene.remove(character.root)
character.dispose()
```

通过 `client` 选项传入的客户端会保持连接。其生命周期由你的应用负责。

### 验证角色

运行应用并发送一条消息。

{% hint style="success" %}
角色会播放待机动画，眼睛会跟随相机，嘴巴会随着语音回复同步移动。
{% endhint %}

如果 `createCharacter` 若拒绝，请查看错误信息。该 [React 指南中的故障排除部分](/api-docs/zh/cha-jian-yu-ji-cheng/web-plugins/convai-embody/add-a-3d-character-to-a-react-app.md#troubleshooting) 也涵盖了相同的错误，因为这两条路径共用同一个加载器。

### 下一步

{% content-ref url="/pages/b60906ed5049da52cc6ddb85571a9101f1eacdb4" %}
[createCharacter 参考](/api-docs/zh/cha-jian-yu-ji-cheng/web-plugins/convai-embody/createcharacter-reference.md)
{% endcontent-ref %}

{% content-ref url="/pages/9dbcb19bcd28e49fb8d9a21383d0cb38608d1127" %}
[Convai Embody 的工作原理](/api-docs/zh/cha-jian-yu-ji-cheng/web-plugins/convai-embody/how-convai-embody-works.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/web-plugins/convai-embody/add-a-3d-character-to-a-three-js-scene.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.
