Компонент dynamic-body

Компонент dynamic-body является частью интеграции физического движка Cannon.js с A-Frame и позволяет создавать объекты с динамическим поведением в 3D-сцене. Он отвечает за физическое моделирование: силы, столкновения, гравитацию и инерцию.

Основные принципы работы

dynamic-body делает объект подвижным и подверженным физическим законам. В отличие от статических тел (static-body), динамическое тело:

  • реагирует на столкновения с другими объектами;
  • подчиняется гравитации сцены;
  • поддерживает силу, импульс и вращение.

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

Подключение и использование

Чтобы использовать dynamic-body, необходимо подключить компонент aframe-physics-system:

<script src="https://cdn.jsdelivr.net/npm/aframe@1.4.2/dist/aframe.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/aframe-physics-system@4.0.1/dist/aframe-physics-system.min.js"></script>

Простейший пример:

<a-scene physics="gravity: -9.8">
  <a-box position="0 5 -5" dynamic-body color="red" width="1" height="1" depth="1"></a-box>
  <a-plane static-body rotation="-90 0 0" width="10" height="10" color="gray"></a-plane>
</a-scene>

В этом примере куб с компонентом dynamic-body падает под действием гравитации и сталкивается с плоскостью.

Настройки компонента

Компонент dynamic-body поддерживает ряд параметров для точного управления физикой:

  • mass — масса тела. По умолчанию 1.
  • shape — форма коллайдера: box, sphere, cylinder, cone, plane, trimesh, compound.
  • linearDamping — затухание линейного движения (0–1). Значение 0 — без сопротивления, 1 — мгновенная остановка.
  • angularDamping — затухание вращения (0–1).
  • allowSleep — разрешение телу “засыпать” при отсутствии движения (true/false).
  • collisionFilterGroup и collisionFilterMask — настройки фильтрации столкновений, позволяют изолировать объекты от столкновений с определёнными группами.

Пример с расширенными настройками:

<a-sphere position="0 10 -5" radius="1" color="blue"
          dynamic-body="mass: 2; shape: sphere; linearDamping: 0.1; angularDamping: 0.2">
</a-sphere>

Работа с формами коллайдера

Выбор формы влияет на точность столкновений и производительность:

  • box — оптимально для прямоугольных объектов.
  • sphere — хорошо подходит для круглых объектов, расчет прост.
  • cylinder/cone — для цилиндров и конусов.
  • trimesh — точное повторение сложной геометрии, но высокая нагрузка на CPU.
  • compound — комбинация нескольких форм, создаёт составные коллайдеры.

Взаимодействие с другими телами

dynamic-body поддерживает столкновения и реакции на силу. Для обработки событий используются стандартные события A-Frame:

  • collide — возникает при столкновении с другим телом.
  • collidestart — начало контакта.
  • collideend — конец контакта.

Пример прослушивания события:

AFRAME.registerComponent('collision-listener', {
  init: function () {
    this.el.addEventListener('collide', function (e) {
      console.log('Столкновение с:', e.detail.body.el);
    });
  }
});
<a-box position="0 5 -5" dynamic-body collision-listener></a-box>

Применение силы и импульса

Динамическое тело можно программно перемещать с помощью методов Cannon.js через компонент dynamic-body:

  • applyForce(forceVec3, worldPoint) — применение силы.
  • applyImpulse(impulseVec3, worldPoint) — мгновенный импульс.
  • applyLocalForce(forceVec3, localPoint) — сила относительно локальной системы координат.
  • applyLocalImpulse(impulseVec3, localPoint) — импульс относительно локальной системы.

Пример импульса при клике:

document.querySelector('a-box').addEventListener('click', function () {
  const body = this.body;
  body.applyImpulse(new CANNON.Vec3(0, 5, 0), body.position);
});

Оптимизация динамических тел

Для сложных сцен важно учитывать производительность:

  • Ограничивать использование trimesh и compound только там, где необходимо.
  • Использовать затухания linearDamping и angularDamping для уменьшения дрожания при падении.
  • Применять allowSleep: true для объектов, которые могут долго находиться в покое, чтобы экономить вычисления.
  • Минимизировать количество динамических тел, если можно заменить на статические тела (static-body) или kinematic (kinematic-body).

Совместная работа с static-body и kinematic-body

dynamic-body хорошо комбинируется с другими типами тел:

  • Static-body — неподвижные объекты, с которыми динамическое тело сталкивается.
  • Kinematic-body — объекты, движущиеся по заданной траектории, не подчиняющиеся гравитации, но влияющие на динамические тела при контакте.

Эта комбинация позволяет создавать полноценные физические сцены: падающие предметы, катящиеся шары, интерактивные платформы и симуляцию среды.

Частые ошибки и тонкости

  • Применение слишком большой массы к небольшим объектам может вызвать “пробивание” сквозь статические тела.
  • Использование trimesh для всех объектов сильно замедляет рендеринг.
  • Без включённого физического движка (physics="true") dynamic-body не работает.
  • Все события столкновения работают только после полной инициализации физического тела.

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