> For the complete documentation index, see [llms.txt](https://docs.decentraland.org/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.decentraland.org/creator/content-creator-zh/chang-jing-sdk7/jiao-hu-xing/npc-avatars.md).

# NPC 头像

显示和控制 NPC 头像

将头像显示为场景中的一个实体。

{% hint style="info" %}
**💡 提示**：试试 [NPC 工具包库](https://github.com/decentraland-scenes/dcl-npc-toolkit) 以便更轻松地处理 NPC，尤其是在需要通过对话树交互时。
{% endhint %}

## 创建一个头像

以下代码片段会创建一个头像，随机生成穿戴物和身体形状，名称为 “NPC”。

```ts
const myAvatar = engine.addEntity()
AvatarShape.create(myAvatar)

Transform.create(myAvatar, {
	position: Vector3.create(4, 0.25, 5),
})
```

当传递数据以生成一个 `AvatarShape`，需要以下字段：

* `id`：（必填）头像的内部标识符

还提供以下可选字段：

* `名称`：显示在头像头顶的名称。默认值：“NPC”。
* `bodyShape`：用于定义使用哪种身体形状的字符串。有效选项为 'urn:decentraland:off-chain:base-avatars:BaseMale' 和 'urn:decentraland:off-chain:base-avatars:BaseFemale'。
* `wearables`：包含头像当前穿戴物 URN 列表的数组。如果穿戴物冲突（例如两个都是帽子），列表中靠后的项会替换前一项。
* `emotes`：包含头像可播放的 NFT 表情动作 URN 列表的数组
* `eyeColor`: *Color3* 用于眼睛颜色（任意颜色均可）
* `skinColor`: *Color3* 用于皮肤颜色（任意颜色均可）
* `hairColor`: *Color3* 用于头发颜色（任意颜色均可）
* `talking`：如果 *真*，它会在名称旁显示一组绿色条形，就像玩家在世界中使用语音聊天时一样。
* <div data-gb-custom-block data-tag="hint" data-style="info" class="hint hint-info"><p><strong>💡 提示</strong>：参见 <a href="/creator/content-creator-zh/chang-jing-sdk7/3d-nei-rong-ji-chu/color-types.md">颜色类型</a> 了解如何设置颜色的更多详情。</p></div>

{% hint style="warning" %}
**📔 注意**： `AvatarShape`组件必须通过以下方式导入：

> `import { AvatarShape } from "@dcl/sdk/ecs"`

参见 [导入](/creator/content-creator-zh/chang-jing-sdk7/ru-men/coding-scenes.md#imports) 了解如何轻松处理这些。
{% endhint %}

{% hint style="warning" %}
**📔 注意**：URN 字段必须遵循与以下相同的格式 [NFTShapes](/creator/content-creator-zh/chang-jing-sdk7/mei-ti/display-a-certified-nft.md): `urn:decentraland:<CHAIN>:<CONTRACT_STANDARD>:<CONTRACT_ADDRESS>:<TOKEN_ID>`
{% endhint %}

## 动画

头像静止时会播放默认的待机动画。

要在头像上播放动画，请设置 `expressionTriggerId` 字符串为你想播放的动画名称。

```ts
const myAvatar = engine.addEntity()
AvatarShape.create(myAvatar, {
	id: '',
	emotes: [],
	wearables: [],
	expressionTriggerId: 'robot',
})

Transform.create(myAvatar, {
	position: Vector3.create(4, 0.25, 5),
})
```

该 `expressionTriggerId` 该字段支持所有 [默认动画](/creator/content-creator-zh/chang-jing-sdk7/jiao-hu-xing/player-avatar.md#default-animations)，以及自定义动画 [来自场景文件](/creator/content-creator-zh/chang-jing-sdk7/jiao-hu-xing/player-avatar.md#custom-animations)，甚至包括发布到市场中的表情动作 URN。

### 循环动画

一个上的动画 `AvatarShape` 只会播放一次；如果你希望头像持续循环播放某个动画，应创建一个系统，每隔几秒告诉它再次播放该动画。

使用 `expressionTriggerTimestamp` 用于重新播放同一个表情动作。此字段的值是一个 [Lamport 时间戳](https://en.wikipedia.org/wiki/Lamport_timestamp)，这意味着它不是时间值，而是每次重复表情动作时加 1 的索引。

因此，当你第一次播放表情动作时，设置 `expressionTriggerTimestamp` 为 *0*。要再次播放该表情动作，你必须将此值更新为 1。这样引擎就知道这是一条新指令，而不是已经执行过的指令。

以下代码片段创建了一个每 2 秒运行一次相同表情动作的系统：

```ts
const myAvatar = engine.addEntity()
AvatarShape.create(myAvatar, {
	id: '',
	emotes: [],
	wearables: [],
	expressionTriggerId: 'clap',
    expressionTriggerTimestamp: 0
})

Transform.create(myAvatar, {
	position: Vector3.create(4, 0.25, 5),
})

let clapTimer = 0
let emoteDuration = 2  // 2 秒

// 系统
engine.addSystem((dt: number) => {
    clapTimer += dt
      
    if (clapTimer >= emoteDuration) {
        // 触发表情动作 clap
        AvatarShape.getMutable(myAvatar).expressionTriggerTimestamp += 1
        
        clapTimer = 0 // 重置计时器
    }
})
```

{% hint style="info" %}
**💡 提示**：你必须知道表情动作的持续时间，并将其设置为系统的持续时间。如果你创建了一个让头像始终保持同一姿势不动的表情动作，建议将表情动作的持续时间设置得比系统更长。这样可以确保在结束并重置动画时不会出现残留伪影。
{% endhint %}

## 从玩家复制穿戴物

以下代码片段会更改 NPC 头像的穿戴物和其他特征，使其与玩家当前穿戴的内容一致。这可用于场景中的人体模型，以展示某件特定穿戴物或表情动作，并与玩家当前装扮结合展示。

```ts
import { getPlayer } from '@dcl/sdk/src/players'


export function swapAvatar(avatar: Entity) {

  let userData = getPlayer()
  console.log(userData)

  if (!userData || !userData.wearables) return

  const mutableAvatar = AvatarShape.getMutable(avatar)

  mutableAvatar.wearables = userData.wearables
  mutableAvatar.bodyShape = userData.avatar?.bodyShapeUrn
  mutableAvatar.eyeColor = userData.avatar?.eyesColor
  mutableAvatar.skinColor = userData.avatar?.skinColor
  mutableAvatar.hairColor = userData.avatar?.hairColor
  
}
```

## 仅显示穿戴物

使用 `showOnlyWearables` 用于仅显示头像所列穿戴物的字段。头像身体的其余部分将不可见。

```ts
const myAvatar = engine.addEntity()
AvatarShape.create(myAvatar, {
	id: '',
	emotes: [],
	wearables: [
    'urn:decentraland:matic:collections-v2:0x90e5cb2d673699be8f28d339c818a0b60144c494:0'
  ],
	showOnlyWearables: true,
})

Transform.create(myAvatar, {
	position: Vector3.create(4, 0.25, 5),
})
```

这对于展示穿戴物很有用，例如在商店中。

{% hint style="info" %}
**💡 提示**：如果某件穿戴物比较小，试着将 `缩放` 的 `Transform` 设置为更大的值。
{% endhint %}

## 将实体附加到 NPC

你可以使用 `AvatarAttach` 功能，将一个实体固定到 NPC 头像的某块骨骼上，例如让 NPC 手中拿着一个物体。该实体会在头像动画播放时与头像一起移动。

要使用此功能，请使用 `id` 属性的值来更改此默认行为，该属性位于任何 UI 实体的 `AvatarShape` 为此头像分配一个任意 id，然后在 `AvatarAttach`。该 id 可以是任何你想要的字符串。

```ts
// 创建 NPC，带有一个 ID
const myAvatar = engine.addEntity()
Transform.create(myAvatar, {
  position: Vector3.create(8, 0.25, 8),
})
AvatarShape.create(myAvatar, {
  id: "my-avatar-id", 
  wearables: [],
  emotes: []
})

// 创建要附加到 NPC 的对象
const attachedEntity = engine.addEntity()
Transform.create(attachedEntity, {
    position: Vector3.create(4, 2, 4),
    scale: Vector3.create(0.15,0.15,0.15)
})
MeshRenderer.setBox(attachedEntity)
Material.setBasicMaterial(attachedEntity, { diffuseColor: Color4.Blue() })
AvatarAttach.create(attachedEntity, {
    avatarId: "my-avatar-id",
    anchorPointId: AvatarAnchorPointType.AAPT_LEFT_HAND
})
```

了解更多有关 `AvatarAttach` 组件 [这里](/creator/content-creator-zh/chang-jing-sdk7/3d-nei-rong-ji-chu/entity-positioning.md#attach-an-entity-to-an-avatar).


---

# 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.decentraland.org/creator/content-creator-zh/chang-jing-sdk7/jiao-hu-xing/npc-avatars.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.
