Жизненный цикл сущностей и компонентов

A-Frame — это высокоуровневая библиотека для работы с WebVR и WebXR, построенная на базе <a-scene> и компонентной архитектуры. Каждая сущность (<a-entity>) и компонент проходят через определённые этапы жизненного цикла, что обеспечивает предсказуемое поведение сцены и упрощает управление состояниями объектов.


Создание и инициализация сущностей

Сущность в A-Frame создаётся с помощью тега <a-entity> или его специализированных версий, таких как <a-box>, <a-sphere> и других. На этапе создания происходит:

  1. Разбор атрибутов сущности (position, rotation, scale и пользовательские компоненты).
  2. Регистрация компонентов, указанных через атрибуты или добавленных программно через метод setAttribute.
  3. Инициализация каждого компонента, вызов их метода init(), если он определён. Это первый этап жизненного цикла компонентов, где можно задавать начальные параметры, кэшировать данные или подписываться на события.

Пример инициализации пользовательского компонента:

AFRAME.registerComponent('spin', {
  schema: { speed: { type: 'number', default: 1 } },

  init: function () {
    this.angle = 0;
  },

  tick: function (time, timeDelta) {
    this.angle += this.data.speed * timeDelta / 1000;
    this.el.object3D.rotation.y = this.angle;
  }
});

На этапе init создаются все необходимые внутренние состояния, но объект ещё не находится в сцене.


Встраивание в сцену и событие loaded

После того как сущность добавлена в сцену через DOM или appendChild, происходит событие loaded. На этом этапе все компоненты сущности гарантированно инициализированы, а их дочерние элементы доступны. Методы жизненного цикла, связанные с этим этапом:

  • update(oldData) — вызывается при изменении свойств компонента после инициализации.
  • play() — активирует компонент, если он был на паузе; часто используется для запуска анимаций, эффектов или логики игры.

Пример:

AFRAME.registerComponent('color-changer', {
  schema: { color: { type: 'color', default: '#FFF' } },

  init: function () {
    console.log('Компонент инициализирован');
  },

  update: function (oldData) {
    if (oldData.color !== this.data.color) {
      this.el.setAttribute('material', 'color', this.data.color);
    }
  },

  play: function () {
    console.log('Компонент активен');
  }
});

Событие loaded у сущности гарантирует доступность всех компонентов сцены, что позволяет запускать синхронизированные процессы.


Активное состояние: tick и управление кадрами

Компоненты, которым необходима регулярная логика, используют метод tick(time, timeDelta). Он вызывается каждый кадр рендеринга и позволяет реализовать анимации, физику и взаимодействия.

Особенности:

  • time — общее время с момента загрузки сцены в миллисекундах.
  • timeDelta — интервал времени между текущим и предыдущим кадром.
  • Методы play() и pause() позволяют включать и отключать вызов tick динамически, что полезно для оптимизации производительности.

Пример динамической паузы компонента:

el.components['spin'].pause();

Динамическое обновление и update

Компоненты могут реагировать на изменения данных через метод update. Вызов setAttribute('component-name', 'property', value) автоматически вызывает update с предыдущими данными. Это позволяет:

  • Поддерживать реактивность компонентов.
  • Обновлять материал, геометрию или поведение без полной переинициализации.

Приостановка и повторный запуск: pause и play

Методы pause и play управляют активностью компонента:

  • pause() — отключает все события и tick, сохраняя текущее состояние.
  • play() — возобновляет работу компонента, может быть вызван при повторном отображении объекта.

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


Удаление сущности и метод remove

При удалении сущности с сцены вызывается метод remove у всех её компонентов. Этот этап жизненного цикла используется для:

  • Очистки ресурсов (текстур, геометрий, событий).
  • Отписки от глобальных обработчиков.
  • Завершения анимаций и физических симуляций.

Пример:

AFRAME.registerComponent('cleanup-example', {
  remove: function () {
    console.log('Компонент удалён и освобождает ресурсы');
  }
});

Взаимодействие жизненного цикла компонентов

Основные методы жизненного цикла компонентов A-Frame:

Метод Этап Назначение
init Инициализация Создание состояния и установка начальных значений
update Обновление свойств Реакция на изменения данных компонента
play Активация Запуск логики компонента, анимаций
pause Приостановка Остановка активной логики для оптимизации
remove Удаление Очистка ресурсов и событий
tick Каждый кадр Постоянная логика и анимации

Понимание этих этапов позволяет строить сложные сцены с управляемой логикой, минимизировать утечки памяти и обеспечивать плавный рендеринг в VR/AR-приложениях.


Жизненный цикл дочерних сущностей

Дочерние элементы <a-entity> наследуют жизненный цикл от родителя:

  1. Дочерние компоненты инициализируются после инициализации родителя.
  2. События play и pause распространяются по иерархии.
  3. Удаление родителя автоматически вызывает remove у всех дочерних сущностей.

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


Жизненный цикл сущностей и компонентов — фундаментальная основа A-Frame, обеспечивающая последовательность и предсказуемость работы VR/AR-приложений. Оптимизация поведения через методы play, pause, tick и remove позволяет создавать динамичные и ресурсоэффективные сцены.