# Animações de Modelos 3D

Modelos 3D em *.glTF* e *.glb* o formato podem incluir quantas animações você quiser neles. As animações dizem à malha como se mover, especificando uma série de *keyframes* que são distribuídos ao longo do tempo, a malha então mistura de uma pose para outra para simular movimento contínuo.

A maioria das animações de modelos 3D são [*skeletal animations*](https://en.wikipedia.org/wiki/Skeletal_animation). Essas animações simplificam a geometria complexa do modelo em uma "figura de pau", vinculando cada vértice da malha ao *bone* mais próximo no *skeleton*. Modeladores ajustam o skeleton em diferentes poses, e a malha estica e se dobra para seguir esses movimentos.

Como alternativa, *vertex animations* animam um modelo sem a necessidade de um skeleton. Essas animações especificam diretamente a posição de cada vértice no modelo. Decentraland também suporta essas animações.

Veja [Animations](https://github.com/decentraland/docs-creator/blob/main/creator/3d-modeling/animations/README.md) para detalhes sobre como criar animações para um modelo 3D. Leia [Shape components](https://docs.decentraland.org/creator/content-creator-pt/scenes-sdk7/essenciais-de-conteudo-3d/shape-components) para instruções sobre como importar um modelo 3D para uma cena.

{% hint style="info" %}
**💡 Tip**: As animações geralmente são melhores para mover algo no lugar, não para alterar a posição de uma entity. Por exemplo, você pode definir uma animação para mover os pés de um personagem no lugar, mas para mudar a localização da entity é melhor usar o componente Transform. Veja [Positioning entities](https://docs.decentraland.org/creator/content-creator-pt/scenes-sdk7/essenciais-de-conteudo-3d/move-entities) para mais detalhes.
{% endhint %}

## Verificar se um modelo 3D tem animações

Nem todos os *arquivo glTF* arquivos incluem animações. Para ver se há alguma disponível, você pode fazer o seguinte:

* Se estiver usando [VS Code](https://code.visualstudio.com/)(recomendado), instale a *GLTF Tools* extensão e visualize o conteúdo de um arquivo glTF lá.
* Abra o [Babylon Sandbox](https://sandbox.babylonjs.com/) site e arraste o arquivo glTF (e quaisquer *.jpg* ou *.bin* dependências) para o navegador.
* Abra o *.glTF* arquivo com um editor de texto e role para baixo até encontrar *"animations":*.

{% hint style="info" %}
**💡 Tip**: Em *skeletal* animações, o nome de uma animação muitas vezes é composto pelo nome do armature, um underscore e o nome da animação. Por exemplo `myArmature_animation1`.
{% endhint %}

## Reprodução automática

Se um modelo 3D incluir alguma animação, o comportamento padrão é que a primeira delas seja sempre reproduzida em loop.

Para evitar esse comportamento, adicione um `Animator` componente à entity que contém o modelo, e então trate a reprodução das animações explicitamente. Se um `Animator` componente estiver presente na entity, todas as animações por padrão ficam em `playing: false` e precisam ser reproduzidas manualmente.

{% hint style="info" %}
**💡 Tip**: No [Scene Editor](https://docs.decentraland.org/creator/content-creator-pt/scene-editor/comecar/about-editor), você pode adicionar um **Animator** componente visualmente. Veja [Add Components](https://docs.decentraland.org/creator/content-creator-pt/scene-editor/construir/components#add-components). Você também pode controlar animações de forma sem código via **Actions**, veja [Tornar qualquer item inteligente](https://docs.decentraland.org/creator/content-creator-pt/scene-editor/interatividade/make-any-item-smart).
{% endhint %}

## Tratar animações explicitamente

Um `Animator` componente é usado para acessar todas as animações da entity e pode ser usado para dizer explicitamente à entity para reproduzir ou parar uma animação. O `Animator` componente inclui um array de `states`, esta lista deve incluir um objeto para cada uma das animações que o modelo 3D pode executar. Um único `Animator` pode incluir quantos estados forem necessários.

```ts
// Create entity
const shark = engine.addEntity()

// Adicione um modelo 3D a ele
GltfContainer.create(shark, {
	src: 'models/shark.glb',
})

Animator.create(shark, {
	states: [
		{
			clip: 'swim',
			playing: true,
			loop: true,
		},
	],
})
```

Cada `state` objeto rastreia se uma animação está atualmente em reprodução.

{% hint style="warning" %}
**📔 Nota**: O `Animator` componente deve ser importado via

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

Veja [Imports](https://docs.decentraland.org/creator/content-creator-pt/primeiros-passos/coding-scenes#imports) para como lidar com estes facilmente.
{% endhint %}

## Buscar uma animação

Busque um clip do `Animator` pelo nome usando a `.Animator.getClip()` função. Esta função retorna uma versão mutável do objeto de estado da animação.

```ts
const swimAnim = Animator.getClip(sharkEntity, 'swim')
```

`Animator.getClip` requer os seguintes parâmetros:

* `entidade`: A entity do `Animator` componente que você deseja consultar.
* `clipName`: String com o nome do clip que você quer buscar.

`Animator.getClip` busca uma versão mutável do estado da animação, para que você possa modificar livremente os valores no que esta função retorna.

```ts
const swimAnim = Animator.getClip(sharkEntity, 'swim')
swimAnim.looping = false
```

{% hint style="warning" %}
**📔 Nota**: Se você tentar usar `Animator.getClip()` para buscar um clip que exista no modelo 3D, mas não esteja listado no `Animator` componente, ela retorna `null`.
{% endhint %}

## Reproduzir uma animação

O `.playing` o campo em um estado de animação determina se a animação está atualmente em reprodução. Note que múltiplas animações podem estar tocando em um único modelo 3D ao mesmo tempo.

Use o `Animator.playSingleAnimation()` função em um `AnimationState` objeto.

```ts
Animator.playSingleAnimation(sharkEntity, 'swim')
```

Se a entity estivesse reproduzindo quaisquer outras animações, `Animator.playSingleAnimation` as para.

`Animator.playSingleAnimation` requer os seguintes parâmetros:

* `entidade`: A entity do `Animator` componente que você deseja afetar.
* `clipName`: String com o nome do clip que você quer reproduzir.
* `resetCursor`: *(opcional)* Se *true*, ela reproduz a animação desde o início, mesmo se a animação estava previamente pausada. Se *false*, ela continuará a reproduzir a animação de onde foi pausada. Padrão: *true*.

```ts
Animator.playSingleAnimation(sharkEntity, 'swim', false)
```

A tabela a seguir resume como `Animator.playSingleAnimation()` se comporta, usando diferentes valores para a propriedade `resetCursor` :

|                            | `reset` = *false* (padrão)          | `reset` = *true*         |
| -------------------------- | ----------------------------------- | ------------------------ |
| **Currently playing**      | Não tem efeito.                     | Reproduz desde o início. |
| **Paused**                 | Retoma do último frame reproduzido. | Reproduz desde o início. |
| **Finished (Non-looping)** | Reproduz desde o início.            | Reproduz desde o início. |

## Animações em loop

Por padrão, as animações são reproduzidas em um loop que continua repetindo a animação para sempre.

Altere essa configuração ajustando o `loop` propriedade no `state` objeto.

```ts
Animator.create(shark, {
	states: [
		{
			clip: 'bite',
			playing: true,
			loop: false,
		},
	],
})
```

Se `quando looping` for definido como *false*, a animação é executada apenas uma vez e então para, permanecendo na postura do último frame.

## Parar uma animação

Para parar todas as animações que uma entity está reproduzindo, use `Animator.stopAllAnimations()`.

```ts
Animator.stopAllAnimations(shark)
```

`Animator.stopAllAnimations` requer os seguintes parâmetros:

* `entidade`: A entity do `Animator` componente que você deseja afetar.
* `resetCursor`: *(opcional)* Se *true*, ela retorna para a postura do primeiro frame da animação. Se *false*, permanece pausada em sua postura atual. Padrão: *true*.

{% hint style="warning" %}
**📔 Nota**: Ao reproduzir uma animação com `Animator.playSingleAnimation`, esta função trata de parar todas as outras animações nos bastidores. Você não precisa parar explicitamente outras animações nesse caso.
{% endhint %}

Quando uma animação não em loop termina, por padrão o modelo 3D permanece na última postura que teve. Para alterar esse comportamento padrão para que, quando a animação terminar, ela volte à primeira postura, defina o `shouldReset` propriedade para *true*.

```ts
Animator.create(shark, {
	states: [
		{
			name: 'bite',
			clip: 'bite',
			playing: true,
			shouldReset: true,
			loop: true,
		},
	],
})
```

Você também pode usar `Animator.stopAllAnimations()` a qualquer momento para definir explicitamente a postura de volta ao primeiro frame da animação.

{% hint style="warning" %}
**📔 Nota**: Redefinir a postura é uma mudança abrupta. Se você quiser fazer o modelo transitar suavemente para outra postura, você pode ou:
{% endhint %}

## Lidar com múltiplas animações

Se um modelo 3D tiver múltiplas animações empacotadas nele, um único `Animator` componente pode lidar com todas elas.

```ts
// Create entity
const shark = engine.addEntity()

// Adicione um modelo 3D a ele
GltfContainer.create(shark, {
	src: 'models/shark.glb'
})

Animator.create(shark, {
	states:[{
			clip: "swim",
			playing: true,
			loop: true
		}. {
			clip: "bite",
			playing: true,
			loop: true
		}
	]
})
```

No exemplo acima, duas animações são tratadas por `state` objetos separados, e então ambas são atribuídas ao mesmo `Animator` component.

Cada bone em uma animação só pode ser afetado por uma animação por vez, a menos que essas animações tenham um `weight` que some até um valor de 1 ou menos.

Se uma animação afeta apenas as pernas de um personagem, e outra afeta apenas a cabeça, então elas podem ser reproduzidas ao mesmo tempo sem problema. Mas se ambas afetam as pernas do personagem, então você deve ou reproduzir apenas uma por vez, ou reproduzi-las com `weight` valores

mais baixos. `Se no exemplo acima, a animação` bite `afeta somente a boca do tubarão, e a animação` swim

{% hint style="warning" %}
**📔 Nota**: `afeta apenas os bones da coluna do tubarão, então elas podem ser reproduzidas ao mesmo tempo se estiverem em camadas separadas.` Animator.playSingleAnim() `playing` para todas as outras animações que a entity está reproduzindo no momento. Para reproduzir múltiplas animações ao mesmo tempo, modifique manualmente a propriedade
{% endhint %}

## na lista de estados da animação.

Velocidade da animação `Altere a velocidade com que uma animação é reproduzida alterando a propriedade` speed

```ts
Animator.create(shark, {
	states: [
		{
			clip: 'swim',
			playing: true,
			loop: true,
			A velocidade padrão é 1.
		},
	],
})
```

speed: 2,

```ts
const swimAnim = Animator.getClip(sharkEntity, 'swim')

Defina a velocidade menor que 1 para reproduzi-la mais devagar, por exemplo 0.5 para reproduzir a meio ritmo. Defina maior que 1 para reproduzi-la mais rápido, por exemplo 2 para reproduzir o dobro da velocidade.
```

## swimAnim.speed = 0.5

O `weight` Peso da animação `weight` a propriedade permite que um único modelo execute múltiplas animações em diferentes camadas ao mesmo tempo, calculando uma média ponderada de todos os movimentos envolvidos na animação. O valor de

determina quanta importância essa animação terá na média. `weight` Por padrão, *1*é igual a `weight` . O valor de *1*.

```ts
Animator.create(shark, {
	states: [
		{
			clip: 'swim',
			playing: true,
			loop: true,
			não pode ser maior que
		},
	],
})
```

O `weight` weight: 0.2,

O valor de todas as animações ativas em uma entity deve somar 1 o tempo todo. Se somar menos que 1, a média ponderada usará a posição padrão do armature para a parte restante do cálculo. *afeta somente a boca do tubarão, e a animação* Por exemplo, no exemplo de código acima, estamos reproduzindo a animação `weight` que só tem um *0.2*de

O `weight` . Esse movimento de natação será bastante sutil: apenas 20% da intensidade que a animação define. Os 80% restantes do cálculo pegam valores da postura padrão do armature. `weight` propriedade de *afeta somente a boca do tubarão, e a animação* a propriedade pode ser usada de maneiras interessantes, por exemplo o

poderia ser ajustado proporcionalmente à rapidez com que o tubarão está nadando, assim você não precisa criar múltiplas animações para natação rápida e lenta. `weight` Você também poderia alterar o valor do

{% hint style="warning" %}
**📔 Nota**gradualmente ao iniciar e parar uma animação para dar uma transição mais natural e evitar saltos da pose padrão para a primeira pose da animação. `weight` : O valor somado de
{% endhint %}

```ts
const swimAnim = Animator.getClip(sharkEntity, 'swim')

de todas as animações que atuam sobre um bone de um modelo 3D não pode ser mais do que 1. Se mais de uma animação estiver afetando os mesmos bones ao mesmo tempo, elas precisam ter seus weights definidos em valores que somem menos de 1.
```
