# Работа с анимациями 3D-объектов

В отличие от [простого редактора](https://mywebar.gitbook.io/mywebar-knowledge-base/yazyk-ru-1/s-chego-nachat/obzor-redaktora), в [продвинутом ](https://dashboard.mywebar.com/mae-editor/)можно более расширенно работать с анимациями. Можно как запускать несколько подряд, так и просто анимировать через определенный промежуток времени.

## Добавление 3D-объекта и его проверка

Для работы с анимациями, первым делом нужно добавить 3D-объект на сцену и проверить его на наличие анимаций.&#x20;

{% hint style="info" %}
О том, как добавлять 3D-объект написано в статье [opisanie-interfeisa](https://mywebar.gitbook.io/mywebar-knowledge-base/yazyk-ru-1/pro-editor/kak-ustroen-pro-editor/opisanie-interfeisa "mention").
{% endhint %}

![](https://16483826-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FQlfxB1bBQeYgEsEfSMqq%2Fuploads%2FDeM0DOe5tTCBwjQbKKyh%2FAnimations_1.jpg?alt=media\&token=f7d78005-79fc-4557-aa44-2d455ce02aec)

У объектов с анимацией появится дополнительный блок справа.

![](https://16483826-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FQlfxB1bBQeYgEsEfSMqq%2Fuploads%2FldDNfbQvLop0yaVMy29P%2FAnimations_1.jpg?alt=media\&token=624f2629-704d-4830-9dc5-6d00bebc017a)

Здесь, в выпадающем списке, вы можете увидеть, сколько дорожек имеет модель. А так же, по нажатию по кнопку **PLAY**, проиграть выбранную анимацию.

![](https://16483826-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FQlfxB1bBQeYgEsEfSMqq%2Fuploads%2FD6WVnakNWJePGYFkgCof%2FAnimations_3.jpg?alt=media\&token=2bd443aa-16e4-49e4-8a2f-8cc0e056bb62)

Таким образом, если все нужные анимации работаю исправно, можно приступать к работе с ними.

## Запуск анимации

Для того чтобы 3D-объект воспроизводил анимацию при запуске сцены, нужно создать [сценарий](https://mywebar.gitbook.io/mywebar-knowledge-base/yazyk-ru-1/kak-ustroen-pro-editor/osnovnye-vozmozhnosti#sozdanie-scenariev-dlya-sceny).

О том, как создавать сценарии читайте [#sozdanie-scenariev-dlya-sceny](https://mywebar.gitbook.io/mywebar-knowledge-base/yazyk-ru-1/kak-ustroen-pro-editor/osnovnye-vozmozhnosti#sozdanie-scenariev-dlya-sceny "mention").

### Запуск одной анимации

Далее, внутри редактора кода созданного сценария, нужно написать несколько строк кода.&#x20;

![](https://16483826-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FQlfxB1bBQeYgEsEfSMqq%2Fuploads%2F2RDCfYbh4UKtQXpBwYIC%2FAnimations_4.jpg?alt=media\&token=2c018da7-62d5-40b2-8760-b2185ec7979e)

Первым делом нужно создать новую переменную, внутри которой будет находиться анимационный клип, который будет запускаться *(строка 1)*.

{% code lineNumbers="true" %}

```javascript
const clip = this.animations[0];
```

{% endcode %}

Давайте разберем этот код: `this` — это обращение к этой 3D-модели (в случае, если скрипт привязан к 3D-объекту), `animations` — массив все анимационных клипов объекта, `[0]` — порядковый номер клипа (отсчет всегда начинается с 0, так как это массив, а последний клип будет иметь число n-1).

{% hint style="info" %}
Если нужно запустить  несколько анимаций, в коде будет использоваться несколько клипов, поэтому нужно создать несколько переменных.
{% endhint %}

Так как в данном случае у модели целых два клипа, нужно создать переменные сразу для них обоих *(строка 1-2)*.

{% code lineNumbers="true" %}

```javascript
const clipOne = this.animations[0];
const clipTwo = this.animations[1];
```

{% endcode %}

Теперь нужно создать `AnimationMixer`. `AnimationMixer` — это проигрыватель для анимации объекта на сцене *(строка 3)*.

{% code lineNumbers="true" %}

```javascript
const clipOne = this.animations[0];
const clipTwo = this.animations[1];
const mixer = new THREE.AnimationMixer(this);
```

{% endcode %}

В качестве параметра метода нужно передавать 3D-объект, который нужно анимировать.

Следующим шагом нужно создать переменную, в которую будет записан метод миксера (`AnimationMixer`**)** [`.clipAction`](https://threejs.org/docs/#api/en/animation/AnimationMixer.clipAction). Данный метод возвращает `AnimationAction`.&#x20;

{% hint style="info" %}
`AnimationAction` нужен для управления анимационными клипами, созданными на строке 1 и 2.
{% endhint %}

Так как у данной модели два анимационных клипа, нужно создать две переменные, которые будут возвращать [`AnimationAction`](https://threejs.org/docs/#api/en/animation/AnimationAction) *(строки 4-5)*.

{% code lineNumbers="true" %}

```javascript
const clipOne = this.animations[0];
const clipTwo = this.animations[1];
const mixer = new THREE.AnimationMixer(this);
const actionforClipOne = mixer.clipAction(clipOne);
const actionforClipTwo = mixer.clipAction(clipTwo);
```

{% endcode %}

Дальше, нужно сделать так, чтобы `AnimationMixer` обновлялся каждый кадр. Если этого не сделать, анимация просто не будет запущена или будет работать неверным образом. Для этого, нужно создать новую переменную, в которой будет помещен объект `THREE.Clock`. Он нужен для отслеживания времени *(строка 1)*.

{% code lineNumbers="true" %}

```javascript
const clock = new THREE.Clock();
const clipOne = this.animations[0];
const clipTwo = this.animations[1];
const mixer = new THREE.AnimationMixer(this);
const actionforClipOne = mixer.clipAction(clipOne);
const actionforClipTwo = mixer.clipAction(clipTwo);
```

{% endcode %}

После этого, нужно создать функцию `update()`. Эта функция, которая вызывается каждый кадр *(строки 8-10)*.

{% code lineNumbers="true" %}

```javascript
const clock = new THREE.Clock();
const clipOne = this.animations[0];
const clipTwo = this.animations[1];
const mixer = new THREE.AnimationMixer(this);
const actionforClipOne = mixer.clipAction(clipOne);
const actionforClipTwo = mixer.clipAction(clipTwo);

function update() {

}
```

{% endcode %}

Внутри этой функции нужно создать условный оператор `if`, который, проверяя присутствие миксера, будет обновлять анимацию каждый кадр. Это будет выглядеть следующим образом *(строки 9-11)*.

{% code lineNumbers="true" %}

```javascript
const clock = new THREE.Clock();
const clipOne = this.animations[0];
const clipTwo = this.animations[1];
const mixer = new THREE.AnimationMixer(this);
const actionforClipOne = mixer.clipAction(clipOne);
const actionforClipTwo = mixer.clipAction(clipTwo);

function update() {
	if (mixer) {
		mixer.update(clock.getDelta());
	}
}
```

{% endcode %}

Все, теперь все готово к запуску анимации. С помощью `AnimationAction`, можно запустить любой клип, к примеру первый *(строка 7)*.

{% code lineNumbers="true" %}

```javascript
const clock = new THREE.Clock();
const clipOne = this.animations[0];
const clipTwo = this.animations[1];
const mixer = new THREE.AnimationMixer(this);
const actionforClipOne = mixer.clipAction(clipOne);
const actionforClipTwo = mixer.clipAction(clipTwo);
actionforClipOne.play();

function update() {
	if (mixer) {
		mixer.update(clock.getDelta());
	}
}
```

{% endcode %}

### Запуск нескольких (двух) анимаций подряд

Теперь, после того, как мы научились запускать одну анимацию, можно перейти к запуску несколько анимаций подряд. Для этого, мы будем пользоваться встроенными в THREE.js часами `THREE.Clock` и функцией `update()`.

Код запуска первой анимации, сделанный выше:

{% code lineNumbers="true" %}

```javascript
const clock = new THREE.Clock();
const clipOne = this.animations[0];
const clipTwo = this.animations[1];
const mixer = new THREE.AnimationMixer(this);
const actionforClipOne = mixer.clipAction(clipOne);
const actionforClipTwo = mixer.clipAction(clipTwo);
actionforClipOne.play();

function update() {
	if (mixer) {
		mixer.update(clock.getDelta());
	}
}
```

{% endcode %}

Далее, нужно создать еще один условный оператор `if` внутри функции `update()`, который будет проверять прошло ли с начала старта сцены время, равное длительности первой анимационной дорожки (`clipOne`). Внутри оператора будет сравниваться количество секунд (`clipOne.duration`) первого клипа с текущим временем (`clock.elapsedTime()`).

Это нужно для того, чтобы остановить воспроизведение анимации первого клипа и сразу же воспроизвести анимацию второго клипа *(строка 13-15)*.

{% code lineNumbers="true" %}

```javascript
const clock = new THREE.Clock();
const clipOne = this.animations[0];
const clipTwo = this.animations[1];
const mixer = new THREE.AnimationMixer(this);
const actionforClipOne = mixer.clipAction(clipOne);
const actionforClipTwo = mixer.clipAction(clipTwo);
actionforClipOne.play();

function update() {
	if (mixer) {
		mixer.update(clock.getDelta());
	}
	if (clipOne.duration < clock.getElapsedTime()) {
	
	} 
}
```

{% endcode %}

Теперь нужно добавить код, который будет выполняться внутри условия. Этот кусок кода должен останавливать воспроизведение первого клипа и запускать второй клип *(строка 14)*.

{% code lineNumbers="true" %}

```javascript
const clock = new THREE.Clock();
const clipOne = this.animations[0];
const clipTwo = this.animations[1];
const mixer = new THREE.AnimationMixer(this);
const actionforClipOne = mixer.clipAction(clipOne);
const actionforClipTwo = mixer.clipAction(clipTwo);
actionforClipOne.play();

function update() {
	if (mixer) {
		mixer.update(clock.getDelta());
	}
	if (clipOne.duration < clock.getElapsedTime()) {
		actionforClipOne.stop();
		actionforClipTwo.play();
	} 
}
```

{% endcode %}

Таким образом, после окончания проигрывания первой анимации модели, сразу же начнется вторая.
