Типичные баги: объекты проваливаются, не сталкиваются, трясутся

Ammo.js — это порт библиотеки Bullet Physics на JavaScript, использующий WebAssembly для симуляции физики. Одной из частых проблем при работе является проваливание объектов сквозь коллайдеры. Основные причины этого:

  1. Неправильная настройка шагов симуляции В Bullet (и Ammo.js) точность столкновений зависит от частоты обновления физического мира. Если шаг симуляции слишком большой, быстрые объекты могут “проскочить” через препятствия. Обычно используют фиксированный шаг, например:

    const deltaTime = 1 / 60; // 60 FPS
    physicsWorld.stepSimulation(deltaTime, 10);

    Параметр 10 задаёт максимальное количество подшагов для интерполяции, что повышает точность.

  2. Размеры и масштаб объектов Bullet работает лучше при объектах масштаба 0.1–10 единиц. Слишком большие или слишком маленькие тела создают нестабильность столкновений. Например, плоскость с размерами 1000 x 1000 может вызвать проблемы с точностью столкновений.

  3. Неправильные формы коллайдеров Использование btBoxShape, btSphereShape или btConvexHullShape должно соответствовать геометрии визуального объекта. Тонкие объекты (например, плоские пластины толщиной <0.1) часто проваливаются. В таких случаях рекомендуется:

    • Добавлять небольшую толщину к плоским объектам.
    • Использовать btCompoundShape для сложных форм.
  4. Слишком высокая скорость объектов Объекты, движущиеся с большой скоростью, требуют continuous collision detection (CCD). В Ammo.js это настраивается через:

    body.setCcdMotionThreshold(0.5);
    body.setCcdSweptSphereRadius(0.2);

    MotionThreshold задаёт минимальное смещение, при котором включается CCD, а SweptSphereRadius — радиус сферы для проверки пересечений.


Объекты не сталкиваются: проверка коллайдеров и слоёв

Нередко возникает ситуация, когда объекты видимы, но не реагируют на столкновения. Возможные причины:

  1. Объект не добавлен в физический мир Проверяется через physicsWorld.addRigidBody(body). Иногда визуальный объект создаётся, а физический телом не управляется.

  2. Неправильный тип тела

    • btRigidBody должен иметь правильный mass:

      • 0 — статическое тело (не двигается)
      • >0 — динамическое тело (подвержено физике) Статические объекты не реагируют на столкновения динамических тел, но участвуют в столкновениях. Если оба тела статические, столкновения не произойдет.
  3. Слои столкновений (collision groups) Ammo.js поддерживает маски столкновений. Пример:

    physicsWorld.addRigidBody(body, group, mask);

    Если group и mask не совпадают, столкновение игнорируется. Частая ошибка — использование одинаковых групп для всех объектов без маски.

  4. Коллайдеры с нулевым объёмом Убедиться, что все формы имеют ненулевой размер, иначе они не участвуют в столкновениях.


Тряска и нестабильность объектов

Тряска часто возникает при слабой стабильности интеграции физики:

  1. Малые массы и большие силы Динамические объекты с очень маленькой массой (<0.1) при стандартных гравитациях начинают резко дергаться. Решение: увеличить массу или уменьшить силу воздействия.

  2. Слишком жёсткие constraints Joint-и и btGeneric6DofConstraint при неправильно подобранных линейных/угловых лимитах создают колебания. Рекомендуется:

    • Настраивать мягкость (setStiffness и setDamping)
    • Использовать setERP (error reduction parameter) для контроля исправления позиций.
  3. Неравномерный шаг симуляции Разные deltaTime при каждом кадре приводят к накоплению ошибок. Фиксированный шаг + интерполяция визуальных объектов решает проблему.


Практические советы по отладке

  • Визуализировать коллайдеры с помощью Ammo.btCollisionWorld debug drawer или Three.js Wireframe для проверки совпадения форм.
  • Логировать позиции и скорости объектов, чтобы понять момент, когда они проваливаются или начинают трястись.
  • Проверять массу, размеры и формы всех тел. Малые или нулевые значения почти всегда вызывают нестабильность.
  • Активировать CCD для быстрых объектов и избегать слишком больших шагов симуляции.

Эти методы позволяют минимизировать типичные баги Ammo.js: проваливание, отсутствие столкновений и тряску объектов. Правильная настройка форм, масс, шагов симуляции и CCD значительно повышает стабильность физического мира.