В A-Frame позиционирование пользователя в пространстве реализуется
через специальный контейнер — rig-объект. Он
представляет собой родительскую сущность (a-entity), внутри
которой располагается камера и, при необходимости, контроллеры.
Перемещение rig приводит к перемещению всей вложенной структуры, что
позволяет управлять позицией игрока или наблюдателя как единого
целого.
Типовая структура:
<a-entity id="rig" position="0 1.6 0">
<a-camera></a-camera>
</a-entity>
В данном примере rig задаёт глобальное положение
пользователя, а камера отвечает за ориентацию и локальные смещения,
получаемые от устройств ввода (мышь, VR-шлем, контроллеры).
В VR-сценах камера получает динамические данные от трекинговой системы: позицию головы и её вращение. Если изменять позицию самой камеры напрямую, возникает конфликт между:
Rig выполняет функцию промежуточного слоя:
Такое разделение устраняет проблему «перезаписи» координат и делает архитектуру предсказуемой.
Позиционирование в A-Frame основано на иерархии сцены. Трансформации применяются по принципу наследования:
Пример:
<a-entity id="rig" position="5 0 0">
<a-entity position="0 1.6 0">
<a-camera></a-camera>
</a-entity>
</a-entity>
Здесь итоговая позиция камеры по оси X будет равна 5, несмотря на то, что внутри вложенной сущности X равен 0.
A-Frame использует правостороннюю систему координат:
Поэтому движение вперёд реализуется уменьшением значения
Z у rig-объекта.
Пример перемещения вперёд:
const rig = document.querySelector('#rig');
rig.object3D.position.z -= 0.1;
Использование object3D даёт доступ к внутреннему объекту
Three.js, лежащему в основе A-Frame.
Часто rig получает позицию 0 1.6 0, где 1.6 — средний
рост глаз человека в метрах. Однако при использовании VR-устройств
высота может задаваться автоматически системой трекинга.
Возможны два подхода:
<a-entity id="rig" position="0 1.6 0">
<a-camera></a-camera>
</a-entity>
<a-entity id="rig">
<a-entity position="0 1.6 0">
<a-camera></a-camera>
</a-entity>
</a-entity>
Второй способ предпочтительнее, если предполагается работа с room-scale VR, поскольку реальная высота пользователя будет добавляться к виртуальной.
Компонент wasd-controls можно назначить на rig:
<a-entity id="rig" wasd-controls>
<a-camera></a-camera>
</a-entity>
Теперь перемещение будет происходить за счёт изменения позиции родительской сущности, а не камеры.
Пример простого компонента:
AFRAME.registerComponent('move-forward', {
tick: function () {
this.el.object3D.position.z -= 0.05;
}
});
Применение:
<a-entity id="rig" move-forward>
<a-camera></a-camera>
</a-entity>
Метод tick вызывается каждый кадр, что делает его
подходящим для анимации перемещений.
Повороты выполняются через изменение свойства rotation
или через доступ к object3D.rotation.
Пример:
rig.object3D.rotation.y += 0.02;
Поворот по оси Y обеспечивает горизонтальное вращение (yaw). При VR-сценариях важно учитывать, что камера уже содержит собственное вращение головы. Поэтому вращение через rig используется для:
Телепортация реализуется мгновенным изменением позиции rig:
rig.setAttribute('position', {x: 10, y: 0, z: -5});
Преимущество такого подхода:
Часто используется совместно с проверкой столкновений и навигационной сеткой.
При работе с физикой (например, через
aframe-physics-system) именно rig становится объектом, к
которому привязывается физическое тело.
Пример:
<a-entity id="rig"
dynamic-body
shape="auto">
<a-camera></a-camera>
</a-entity>
В этом случае перемещение происходит через физический движок, а не прямое изменение координат.
Альтернативный способ — проверка пересечений вручную перед изменением позиции.
Резкое изменение координат может вызывать дискомфорт в VR. Для плавности применяется интерполяция.
Пример линейной интерполяции:
const target = new THREE.Vector3(5, 0, -3);
rig.object3D.position.lerp(target, 0.1);
Такое обновление выполняется в tick, обеспечивая
постепенное приближение к целевой точке.
В VR-контексте структура rig может расширяться:
<a-entity id="rig">
<a-entity position="0 1.6 0">
<a-camera></a-camera>
<a-entity laser-controls="hand: left"></a-entity>
<a-entity laser-controls="hand: right"></a-entity>
</a-entity>
</a-entity>
Перемещение rig автоматически переносит и контроллеры, поскольку они находятся внутри иерархии.
Получение мировой позиции:
const worldPosition = new THREE.Vector3();
rig.object3D.getWorldPosition(worldPosition);
Это важно при:
В мультиплеерных сценах передаётся именно позиция rig, а не камеры. Это позволяет:
Часто создаётся отдельная модель аватара, привязанная к rig, а камера остаётся скрытой.
1. Перемещение камеры вместо rig Приводит к конфликтам с трекингом.
2. Неправильная высота Y Вызывает «погружение» в пол или зависание над поверхностью.
3. Игнорирование иерархии Сложности при добавлении контроллеров или физики.
4. Резкие изменения позиции в VR Провоцируют укачивание.
Позиционирование rig-объекта формирует основу навигационной логики сцены и определяет корректность взаимодействия пользователя с виртуальным пространством.