Использование ghost-объектов как триггеров

Ghost-объекты (или невидимые коллайдеры) в Ammo.js представляют собой специальные объекты, которые участвуют в физическом мире, но не подвергаются стандартной динамике: на них не действуют силы, не учитывается масса и они не сталкиваются с другими объектами обычным образом. Основная цель ghost-объектов — фиксировать зоны взаимодействия и использовать их как триггеры для детектирования пересечений.

Ghost-объект создаётся с помощью класса btGhostObject, который наследуется от btCollisionObject. Для него можно задать форму коллайдера (btCollisionShape), позицию и ориентацию в мире.

const ghost = new Ammo.btGhostObject();
ghost.setCollisionShape(boxShape);
ghost.setWorldTransform(transform);
ghost.setCollisionFlags(Ammo.cf_noContactResponse);

Ключевой момент: флаг cf_noContactResponse отключает физическую реакцию на столкновения. Ghost-объект может пересекать другие тела, не вызывая физического отката или смещения.


Настройка формы и позиции

Форма ghost-объекта задаётся любым типом btCollisionShape: btBoxShape, btSphereShape, btCylinderShape и т.д.

const halfExtents = new Ammo.btVector3(1, 1, 1);
const boxShape = new Ammo.btBoxShape(halfExtents);

Положение и ориентация задаются через btTransform:

const transform = new Ammo.btTransform();
transform.setIdentity();
transform.setOrigin(new Ammo.btVector3(0, 0, 0));
ghost.setWorldTransform(transform);

Ghost-объект можно обновлять в процессе симуляции, перемещая его вручную или синхронизируя с другими объектами.


Добавление ghost-объекта в мир

Чтобы ghost-объект начал отслеживать пересечения, его необходимо добавить в физический мир через btCollisionWorld. Если используется btDiscreteDynamicsWorld, ghost-объект добавляется как обычный коллайдер:

dynamicsWorld.addCollisionObject(
    ghost,
    Ammo.CollisionFilterGroups.SensorTrigger,
    Ammo.CollisionFilterGroups.All
);

Пояснение параметров:

  • Первый — сам ghost-объект.
  • Второй — группа коллизий объекта (например, сенсор).
  • Третий — маска коллизий, определяющая, с кем объект может пересекаться.

Детектирование пересечений

Ghost-объекты предоставляют методы для получения списка пересечений с другими телами. Основной метод — getOverlappingPairs(), возвращающий массив объектов, с которыми произошло пересечение на текущем шаге симуляции.

const numOverlaps = ghost.getNumOverlappingObjects();
for (let i = 0; i < numOverlaps; i++) {
    const overlappingObject = ghost.getOverlappingObject(i);
    // действия при пересечении
}

Это позволяет реализовать триггеры: зоны активации, детекторы входа/выхода, зоны повреждения и прочее.

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


Обновление и синхронизация

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

const newTransform = new Ammo.btTransform();
newTransform.setIdentity();
newTransform.setOrigin(new Ammo.btVector3(x, y, z));
ghost.setWorldTransform(newTransform);

При этом getOverlappingPairs() будет автоматически учитывать новые позиции.

Для сложных сцен часто создают массив ghost-объектов и в цикле проверяют пересечения, чтобы реализовать массовые триггеры или зоны с разной логикой.


Практические применения

  1. Детекторы входа/выхода в зоны: зона действия магии, область с ловушкой, контроль зоны безопасности.
  2. Триггеры для событий: включение анимаций, запуск скриптов, подсчёт очков.
  3. Временные сенсоры: объекты, которые появляются на короткое время для детектирования столкновений без физического влияния.
  4. Оптимизация: ghost-объекты позволяют отслеживать коллизии без затрат на динамическое взаимодействие и расчёт сил.

Ограничения и нюансы

  • Ghost-объекты не могут толкать динамические тела; они только фиксируют пересечения.
  • Для точного детектирования с быстрыми объектами следует использовать шаг симуляции с достаточно малым dt, иначе объект может “пройти сквозь” триггер.
  • Пересечения с другими ghost-объектами также фиксируются, если настроены соответствующие фильтры коллизий.
  • Для сложных форм (convex, concave) ghost-объекты могут потребовать дополнительных оптимизаций для производительности.

Интеграция с игровыми объектами

Ghost-объект можно привязать к визуальному объекту или персонажу. Например, для персонажа создаётся невидимая сфера вокруг модели, которая отслеживает сбор предметов:

const sensorShape = new Ammo.btSphereShape(2);
const sensor = new Ammo.btGhostObject();
sensor.setCollisionShape(sensorShape);
sensor.setCollisionFlags(Ammo.cf_noContactResponse);
dynamicsWorld.addCollisionObject(sensor, Ammo.CollisionFilterGroups.SensorTrigger, Ammo.CollisionFilterGroups.All);

// в игровом цикле синхронизация с позицией персонажа
sensor.setWorldTransform(characterTransform);

Таким образом, ghost-объекты становятся эффективным инструментом для логики взаимодействия без физического воздействия, позволяя строить зоны и триггеры любой сложности в мире Ammo.js.