# Avatares NPC

Mostrar un avatar como una entidad en una escena.

{% hint style="info" %}
**💡 Consejo**: Prueba la [biblioteca NPC Toolkit](https://github.com/decentraland-scenes/dcl-npc-toolkit) para una experiencia más sencilla al trabajar con NPCs, especialmente si necesitas interactuar a través de un árbol de conversación.
{% endhint %}

## Crear un avatar

El siguiente fragmento crea un avatar con wearables aleatorios y body shape, y nombre "NPC".

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

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

Al pasar datos para generar un `AvatarShape`, se requieren los siguientes campos:

* `id`: (obligatorio) Identificador interno para el Avatar

También están disponibles los siguientes campos opcionales:

* `name`: Nombre para mostrar sobre la cabeza del Avatar. Predeterminado: "NPC".
* `bodyShape`: Cadena para definir qué body shape usar. Las opciones válidas son 'urn:decentraland:off-chain:base-avatars:BaseMale' y 'urn:decentraland:off-chain:base-avatars:BaseFemale'.
* `wearables`: Array con la lista de URNs de los wearables que el avatar tiene puestos actualmente. Si los wearables entran en conflicto (como si dos de ellos fueran sombreros), el último de la lista reemplaza al otro.
* `emotes`: Array con la lista de URNs de emotes NFT que el avatar es capaz de reproducir
* `eyeColor`: *Color3* para el color de ojos (cualquier color es válido)
* `skinColor`: *Color3* para el color de piel (cualquier color es válido)
* `hairColor`: *Color3* para el color de cabello (cualquier color es válido)
* `talking`: Si *true*, muestra un conjunto verde de barras junto al nombre, como cuando los jugadores usan chat de voz en el mundo.
* <div data-gb-custom-block data-tag="hint" data-style="info" class="hint hint-info"><p><strong>💡 Consejo</strong>: Consulta <a href="/pages/f2d3e2d961724e4ac3d95ea14743fa2ebc06e8ed">tipos de color</a> para más detalles sobre cómo establecer colores.</p></div>

{% hint style="warning" %}
**📔 Nota**: La `AvatarShape`component debe importarse mediante

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

Consulta [Imports](/creator/content-creator-es/scenes-sdk7/primeros-pasos/coding-scenes.md#imports) para ver cómo manejar esto fácilmente.
{% endhint %}

{% hint style="warning" %}
**📔 Nota**: Los campos URN deben seguir el mismo formato usado para [NFTShapes](/creator/content-creator-es/scenes-sdk7/media/display-a-certified-nft.md): `urn:decentraland:<CHAIN>:<CONTRACT_STANDARD>:<CONTRACT_ADDRESS>:<TOKEN_ID>`
{% endhint %}

## Animations

Los Avatars reproducen animaciones idle predeterminadas mientras están quietos.

Para reproducir animaciones en el avatar, establece la `expressionTriggerId` cadena con el nombre de la animación que quieres reproducir.

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

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

El `expressionTriggerId` el campo admite todas las [animaciones predeterminadas](/creator/content-creator-es/scenes-sdk7/interactividad/player-avatar.md#default-animations), así como animaciones personalizadas [desde un archivo de escena](/creator/content-creator-es/scenes-sdk7/interactividad/player-avatar.md#custom-animations), e incluso URNs de emotes publicados en el marketplace.

### Animaciones en bucle

Las animaciones en un `AvatarShape` se reproducen una sola vez; si quieres que el avatar siga repitiendo una animación, debes crear un system que le indique reproducir la animación de nuevo cada par de segundos.

Usa la `expressionTriggerTimestamp` para volver a reproducir un mismo emote. El valor de este campo es un [timestamp de Lamport](https://en.wikipedia.org/wiki/Lamport_timestamp), lo que significa que no es un valor de tiempo, sino más bien un índice que aumenta en 1 por cada repetición del emote.

Así que la primera vez que reproduces un emote, estableces `expressionTriggerTimestamp` en *0*. Para volver a reproducir el emote, debes actualizar este valor a 1. Así es como el engine sabe que esta es una nueva instrucción y no una instrucción sobre la que ya actuó.

El siguiente fragmento crea un system que ejecuta el mismo emote cada 2 segundos:

```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 segundos

// system
engine.addSystem((dt: number) => {
    clapTimer += dt
      
    if (clapTimer >= emoteDuration) {
        // Trigger the clap emote
        AvatarShape.getMutable(wearable).expressionTriggerTimestamp =+ 1 
        
        clapTimer = 0 // Reset timer
    }
})
```

{% hint style="info" %}
**💡 Consejo**: Debes conocer la duración del emote y hacer que esa sea la duración del system. Si creas un emote que deja al avatar inmóvil en una misma pose, es recomendable hacer que la duración del emote sea mayor que la del system. De ese modo, puedes asegurarte de que no haya artefactos al finalizar y reiniciar la animación.
{% endhint %}

## Copiar wearables del jugador

El siguiente fragmento cambia los wearables y otras características de un avatar NPC para que coincidan con las que el jugador tiene puestas actualmente. Esto podría usarse en una escena como un maniquí, para mostrar un wearable o emote en particular combinado con el outfit actual del jugador.

```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
  
}
```

## Mostrar solo wearables

Usa la `show_only_wearables` campo para mostrar solo los wearables enumerados de un avatar. El resto del cuerpo del avatar será invisible.

```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),
})
```

Esto es útil para mostrar wearables, por ejemplo en una tienda.

{% hint style="info" %}
**💡 Consejo**: Si un wearable es bastante pequeño, intenta establecer el `scale` del `Transform` a un valor mayor.
{% endhint %}

## Adjuntar una entidad a un NPC

Puedes usar la `AvatarAttach` función para fijar una entidad a uno de los huesos de un avatar NPC, por ejemplo para que el NPC esté sosteniendo un objeto en la mano. La entidad se moverá junto con el avatar cuando se anime.

Para usar esta función, usa el `id` en el componente `AvatarShape` para asignar un id arbitrario a este avatar, y luego referencia ese id en el `AvatarAttach`. El id puede ser cualquier cadena que quieras.

```ts
// Crear NPC, con un ID
const myAvatar = engine.addEntity()
Transform.create(myAvatar, {
  position: Vector3.create(8, 0.25, 8),
})
AvatarShape.create(myAvatar, {
  id: "my-avatar-id", 
  wearables: [],
  emotes: []
})

// Crear objeto para adjuntar al 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
})
```

Aprende más sobre el `AvatarAttach` componente [aquí](/creator/content-creator-es/scenes-sdk7/esenciales-de-contenido-3d/entity-positioning.md#attach-an-entity-to-an-avatar).


---

# Agent Instructions: 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:

```
GET https://docs.decentraland.org/creator/content-creator-es/scenes-sdk7/interactividad/npc-avatars.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
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.
