A-Frame — это высокоуровневая WebVR/AR библиотека, построенная на основе three.js, которая позволяет создавать интерактивные 3D-сцены с использованием HTML-подобного синтаксиса. Важным аспектом интерактивности является обнаружение столкновений (collision detection), которое позволяет управлять движением объектов, ограничивать перемещение персонажей или реагировать на взаимодействие объектов сцены.
В A-Frame столкновения реализуются через компоненты, пользовательские скрипты и физические движки.
aframe-extras и встроенных решенийБиблиотека aframe-extras предоставляет компонент
collision-detection, упрощающий работу со
столкновениями.
Пример подключения:
<script src="https://cdn.jsdelivr.net/gh/donmccurdy/aframe-extras@6.1.1/dist/aframe-extras.min.js"></script>
Пример использования компонента:
<a-entity id="player"
movement-controls
collision-detection="objects: .collidable">
</a-entity>
<a-box class="collidable" position="0 1 -5" depth="1" height="1" width="1"></a-box>
Здесь
collision-detection="objects: .collidable"
означает, что объект player будет проверять столкновения с
любыми объектами, имеющими класс collidable.
Особенности работы:
collidestart,
collideend, которые можно использовать для логики
игры:const player = document.querySelector('#player');
player.addEventListener('collidestart', (e) => {
console.log('Столкновение началось с', e.detail.body.el);
});
player.addEventListener('collideend', (e) => {
console.log('Столкновение закончилось с', e.detail.body.el);
});
Можно реализовать собственное отслеживание столкновений без сторонних
библиотек, используя tick метод и
Bounding Box объектов.
Пример компонента:
AFRAME.registerComponent('simple-collider', {
schema: {
targets: {type: 'selectorAll'}
},
init: function () {
this.elBox = new THREE.Box3().setFromObject(this.el.object3D);
},
tick: function () {
this.elBox.setFromObject(this.el.object3D);
this.data.targets.forEach(target => {
const targetBox = new THREE.Box3().setFromObject(target.object3D);
if (this.elBox.intersectsBox(targetBox)) {
this.el.emit('collision', {target: target});
}
});
}
});
Использование:
<a-entity id="player" simple-collider="targets: .obstacle"></a-entity>
<a-box class="obstacle" position="2 0 -3"></a-box>
События collision можно обрабатывать для изменения
поведения игрока или запуска анимаций.
cannon.js и ammo.jsДля более реалистичных столкновений рекомендуется использовать физические движки, интегрированные в A-Frame:
aframe-physics-system (на основе
cannon.js)ammo.js (через aframe-extras или кастомные
компоненты)Подключение cannon.js:
<script src="https://cdn.jsdelivr.net/npm/aframe-physics-system@4.0.1/dist/aframe-physics-system.min.js"></script>
Пример физического объекта:
<a-entity id="player" dynamic-body position="0 1 0"></a-entity>
<a-box static-body position="0 0 -5" width="2" height="2" depth="2"></a-box>
dynamic-body — объект с физикой, подвержен гравитации и
столкновениям.static-body — неподвижный объект, служит
препятствием.body-collide:player.addEventListener('collide', (e) => {
console.log('Игрок столкнулся с', e.detail.body.el);
});
Преимущество физического движка в том, что столкновения учитывают форму объекта, массу и физические силы, что невозможно при простом bounding box подходе.
При работе с большим количеством объектов столкновения стоит учитывать:
tick, применяя
интервалы проверки (setInterval) или
requestAnimationFrame с логикой фильтрации.static-body.Часто используется подход: визуальный объект и невидимый коллайдер.
<a-box visible="false" class="collider" static-body position="0 0 -5" width="2" height="2" depth="2"></a-box>
<a-box position="0 0 -5" color="red"></a-box>
collider.cannon.js или
ammo.js.collide,
collision, collidestart,
collideend) позволяют строить логику игрового мира.Такой подход обеспечивает масштабируемость и гибкость сцены, позволяя создавать как простые VR-игры, так и сложные интерактивные приложения в A-Frame.