Отключение столкновений между конкретными парами тел

В физическом движке Oimo.js управление взаимодействием объектов реализуется через систему коллизий, основанную на collision groups и collision masks, а также через возможность прямого исключения столкновений между конкретными телами. Это особенно важно при создании сложных симуляций, где одни объекты должны проходить сквозь другие, а другие — взаимодействовать обычным образом.

Основные концепции коллизий

Каждое тело (OIMO.Body) в Oimo.js имеет следующие свойства, влияющие на обработку столкновений:

  • collisionGroup — числовой идентификатор группы, к которой принадлежит тело.
  • collisionMask — битовая маска, определяющая, с какими группами тело может взаимодействовать.

При проверке столкновений движок анализирует выражение:

(bodyA.collisionGroup & bodyB.collisionMask) !== 0 && (bodyB.collisionGroup & bodyA.collisionMask) !== 0

Если результат false, столкновение между телами игнорируется на уровне движка.

Отключение столкновений между конкретными телами

Для случаев, когда необходимо запретить столкновения не всей группы объектов, а отдельных экземпляров, Oimo.js предоставляет метод setNoCollisionWith через внутренние настройки contactManager или прямую манипуляцию shape.

Пример отключения столкновений между двумя телами:

const bodyA = world.add({ type: 'box', size: [1,1,1], pos: [0,5,0] });
const bodyB = world.add({ type: 'sphere', size: [1], pos: [0,0,0] });

// Отключение столкновений между bodyA и bodyB
bodyA.shapes.forEach(shapeA => {
  bodyB.shapes.forEach(shapeB => {
    shapeA.setNoCollisionWith(shapeB);
  });
});

В данном примере для каждой формы тела bodyA вызывается метод setNoCollisionWith для всех форм тела bodyB. После этого движок полностью игнорирует любые контакты между этими телами, независимо от групп и масок.

Тонкости использования

  1. Множественные формы (shapes) Если тело состоит из нескольких форм, отключение столкновений нужно выполнять для каждой формы отдельно. Пропуск одной формы приведёт к частичному взаимодействию.

  2. Динамическое отключение Можно отключать или включать столкновения во время симуляции. Это полезно для временных эффектов, например, при телепортации или активации фазового прохождения объекта.

// Включение столкновений обратно
shapeA.enableCollisionWith(shapeB);
  1. Производительность Прямое отключение отдельных контактов более эффективно, чем управление через группы и маски, когда нужно исключить лишь несколько пар тел среди сотен объектов.

  2. Совместимость с контактами Даже если столкновение отключено, события onCollision или onContact для этих форм не будут срабатывать, что важно учитывать при логике игрового или симуляционного мира.

Применение в сложных системах

  • Проходящие платформы и триггеры — объекты могут пересекать платформы без физического взаимодействия, сохраняя при этом обработку столкновений с другими объектами.
  • Механизмы сцепления или магнитные эффекты — объекты могут быть привязаны друг к другу, не вступая в коллизию, но оставаясь в пределах физического мира.
  • Игровые персонажи с союзниками — отключение столкновений между союзными телами позволяет моделировать прохождение через друг друга без нарушения остальных взаимодействий.

Практическая реализация

Рекомендуется хранить список исключённых пар тел и выполнять отключение при их добавлении в мир или при изменении состояния. Например, можно создать утилиту:

function disableCollisionBetween(body1, body2) {
  body1.shapes.forEach(s1 => {
    body2.shapes.forEach(s2 => s1.setNoCollisionWith(s2));
  });
}

function enableCollisionBetween(body1, body2) {
  body1.shapes.forEach(s1 => {
    body2.shapes.forEach(s2 => s1.enableCollisionWith(s2));
  });
}

Такой подход позволяет централизованно управлять исключениями и избегать дублирования кода.

Рекомендации по интеграции

  • Использовать setNoCollisionWith только для действительно необходимых исключений, чтобы не усложнять логику симуляции.
  • Совмещать с группами и масками для оптимизации больших сцен.
  • Проверять наличие форм в теле перед вызовом методов, чтобы избежать ошибок при динамическом изменении структуры тела.

Отключение столкновений между конкретными телами в Oimo.js обеспечивает гибкость симуляции, позволяя создавать динамичные сцены с точным контролем физического взаимодействия объектов.