Ammo.js — это порт библиотеки Bullet Physics на JavaScript, использующий WebAssembly для симуляции физики. Одной из частых проблем при работе является проваливание объектов сквозь коллайдеры. Основные причины этого:
Неправильная настройка шагов симуляции В Bullet (и Ammo.js) точность столкновений зависит от частоты обновления физического мира. Если шаг симуляции слишком большой, быстрые объекты могут “проскочить” через препятствия. Обычно используют фиксированный шаг, например:
const deltaTime = 1 / 60; // 60 FPS
physicsWorld.stepSimulation(deltaTime, 10);
Параметр 10 задаёт максимальное количество подшагов для
интерполяции, что повышает точность.
Размеры и масштаб объектов Bullet работает лучше
при объектах масштаба 0.1–10 единиц. Слишком большие
или слишком маленькие тела создают нестабильность столкновений.
Например, плоскость с размерами 1000 x 1000 может вызвать
проблемы с точностью столкновений.
Неправильные формы коллайдеров Использование
btBoxShape, btSphereShape или
btConvexHullShape должно соответствовать геометрии
визуального объекта. Тонкие объекты (например, плоские пластины толщиной
<0.1) часто проваливаются. В таких случаях рекомендуется:
btCompoundShape для сложных форм.Слишком высокая скорость объектов Объекты, движущиеся с большой скоростью, требуют continuous collision detection (CCD). В Ammo.js это настраивается через:
body.setCcdMotionThreshold(0.5);
body.setCcdSweptSphereRadius(0.2);
MotionThreshold задаёт минимальное смещение, при котором
включается CCD, а SweptSphereRadius — радиус сферы для
проверки пересечений.
Нередко возникает ситуация, когда объекты видимы, но не реагируют на столкновения. Возможные причины:
Объект не добавлен в физический мир Проверяется
через physicsWorld.addRigidBody(body). Иногда визуальный
объект создаётся, а физический телом не управляется.
Неправильный тип тела
btRigidBody должен иметь правильный
mass:
0 — статическое тело (не двигается)>0 — динамическое тело (подвержено физике)
Статические объекты не реагируют на столкновения динамических тел, но
участвуют в столкновениях. Если оба тела статические, столкновения не
произойдет.Слои столкновений (collision groups) Ammo.js поддерживает маски столкновений. Пример:
physicsWorld.addRigidBody(body, group, mask);
Если group и mask не совпадают,
столкновение игнорируется. Частая ошибка — использование одинаковых
групп для всех объектов без маски.
Коллайдеры с нулевым объёмом Убедиться, что все формы имеют ненулевой размер, иначе они не участвуют в столкновениях.
Тряска часто возникает при слабой стабильности интеграции физики:
Малые массы и большие силы Динамические объекты
с очень маленькой массой (<0.1) при стандартных
гравитациях начинают резко дергаться. Решение: увеличить массу или
уменьшить силу воздействия.
Слишком жёсткие constraints Joint-и и
btGeneric6DofConstraint при неправильно подобранных
линейных/угловых лимитах создают колебания. Рекомендуется:
setStiffness и
setDamping)setERP (error reduction parameter) для
контроля исправления позиций.Неравномерный шаг симуляции Разные
deltaTime при каждом кадре приводят к накоплению ошибок.
Фиксированный шаг + интерполяция визуальных объектов решает
проблему.
Ammo.btCollisionWorld debug drawer или Three.js
Wireframe для проверки совпадения форм.Эти методы позволяют минимизировать типичные баги Ammo.js: проваливание, отсутствие столкновений и тряску объектов. Правильная настройка форм, масс, шагов симуляции и CCD значительно повышает стабильность физического мира.