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-объект начал отслеживать пересечения, его необходимо
добавить в физический мир через btCollisionWorld. Если
используется btDiscreteDynamicsWorld, ghost-объект
добавляется как обычный коллайдер:
dynamicsWorld.addCollisionObject(
ghost,
Ammo.CollisionFilterGroups.SensorTrigger,
Ammo.CollisionFilterGroups.All
);
Пояснение параметров:
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-объектов и в цикле проверяют пересечения, чтобы реализовать массовые триггеры или зоны с разной логикой.
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.