Анимации внутри glTF-моделей

A-Frame поддерживает анимации, встроенные в форматы 3D-моделей, включая glTF и GLB. Эти форматы позволяют хранить скелетные анимации (skeletal/bone animations) и анимированные трансформации объектов (node animations). Важное отличие заключается в том, что скелетные анимации управляют костями модели, а node-анимации изменяют позицию, вращение и масштаб конкретных узлов сцены.

Для работы с анимациями glTF используется компонент gltf-model и дополнительный компонент animation-mixer, который интегрирован в A-Frame и работает на основе Three.js. Он автоматически считывает доступные анимации из модели и предоставляет возможность их управления.

<a-entity gltf-model="#robotModel" animation-mixer></a-entity>

В этом примере animation-mixer подключается к модели робота. По умолчанию воспроизводится первая анимация из файла glTF.


Управление анимациями

Компонент animation-mixer позволяет гибко управлять анимациями:

  • Выбор конкретной анимации: Атрибут clip позволяет указать имя или индекс анимации:
<a-entity gltf-model="#robotModel" 
          animation-mixer="clip: Walk"></a-entity>
  • Повторение и зацикливание: Атрибут loop управляет цикличностью:
<a-entity gltf-model="#robotModel" 
          animation-mixer="clip: Run; loop: repeat"></a-entity>

Допустимые значения: repeat (циклично), once (один раз), pingpong (обратное воспроизведение).

  • Скорость воспроизведения: Атрибут timeScale изменяет скорость анимации:
<a-entity gltf-model="#robotModel" 
          animation-mixer="clip: Walk; timeScale: 2"></a-entity>

Значение 2 ускоряет анимацию в два раза.


Управление анимациями через JavaScript

Для динамического контроля анимаций используется стандартный подход Three.js через animation-mixer:

const entity = document.querySelector('#robot');
const mixer = entity.components['animation-mixer'].mixer;
const clips = entity.getObject3D('mesh').animations;

// Воспроизведение конкретной анимации
const action = mixer.clipAction(clips.find(clip => clip.name === 'Jump'));
action.reset().play();

// Плавное смешивание (crossfade) между анимациями
const runAction = mixer.clipAction(clips.find(clip => clip.name === 'Run'));
action.crossFadeTo(runAction, 0.5, true);

Метод crossFadeTo позволяет делать плавные переходы между анимациями, что особенно важно для реалистичных движений персонажей.


Смешивание нескольких анимаций

A-Frame и Three.js поддерживают анимационные слои, что позволяет одновременно проигрывать несколько анимаций:

const walkAction = mixer.clipAction(clips.find(c => c.name === 'Walk'));
const waveAction = mixer.clipAction(clips.find(c => c.name === 'Wave'));

walkAction.play();
waveAction.play();
waveAction.setEffectiveWeight(0.5); // Полупрозрачное смешивание

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


Работа с событиями анимаций

Компонент animation-mixer может реагировать на события, передаваемые Three.js:

entity.addEventListener('animation-finished', (event) => {
    console.log('Анимация завершена:', event.detail.action._clip.name);
});

Эта функциональность особенно полезна для игровых механик, когда необходимо выполнять действия после завершения определенной анимации.


Подготовка glTF для A-Frame

Для корректной работы анимаций в A-Frame модель должна:

  1. Иметь именованные анимационные клипы.
  2. Не содержать анимации, управляемые внешними скриптами движка (например, Unity Animator), так как они не экспортируются в glTF.
  3. Использовать единообразные масштабы и ориентацию, чтобы анимации корректно воспроизводились в веб-сцене.

Программы типа Blender или Maya позволяют экспортировать анимации прямо в glTF, сохраняя все ключевые кадры и скелетные структуры.


Рекомендации по оптимизации

  • Ограничивать количество одновременно активных анимаций для снижения нагрузки на GPU.
  • Использовать низкополигональные модели с упрощёнными скелетными структурами.
  • Минимизировать количество keyframe’ов в длительных анимациях при сохранении плавности.
  • Применять lod (level of detail) для анимационных моделей, чтобы экономить ресурсы на дальнем плане.

Совместное использование с A-Frame-анимациями

A-Frame позволяет комбинировать animation-mixer с собственным компонентом animation, создавая эффекты перемещения или вращения всей модели:

<a-entity gltf-model="#robotModel" 
          animation-mixer="clip: Walk"
          animation="property: position; to: 0 0 -5; dur: 3000; loop: true"></a-entity>

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