В физическом движке, основанном на библиотеке Bullet Physics, существует класс объектов, которые участвуют в широкофазной и узкофазной проверке пересечений, но не вступают в физическое взаимодействие с другими телами. В JavaScript-порте Ammo.js эти объекты представлены классами:
btGhostObjectbtPairCachingGhostObjectGhost-объекты предназначены для:
Главная особенность — объект регистрируется в физическом мире, но не генерирует сил реакции.
Ghost-объекты являются наследниками btCollisionObject.
Это означает:
btCollisionShape);btTransform);Однако они:
btGhostObject — базовый класс триггерного объекта. Он
отслеживает пересечения с другими телами и хранит список
overlapping-объектов.
const transform = new Ammo.btTransform();
transform.setIdentity();
transform.setOrigin(new Ammo.btVector3(0, 5, 0));
const shape = new Ammo.btBoxShape(new Ammo.btVector3(1, 1, 1));
const ghostObject = new Ammo.btGhostObject();
ghostObject.setCollisionShape(shape);
ghostObject.setWorldTransform(transform);
Ghost-объект необходимо добавить в физический мир через:
physicsWorld.addCollisionObject(
ghostObject,
collisionGroup,
collisionMask
);
Важно корректно настроить:
Без правильной маски пересечения обнаружены не будут.
После шага симуляции:
physicsWorld.stepSimulation(deltaTime, 10);
Можно получить список пересечений:
const numOverlapping = ghostObject.getNumOverlappingObjects();
for (let i = 0; i < numOverlapping; i++) {
const overlappingObject = ghostObject.getOverlappingObject(i);
}
Метод getOverlappingObject(i) возвращает
btCollisionObject.
btGhostObject не кэширует контактные пары. Это
означает:
Для более продвинутых сценариев используется
btPairCachingGhostObject.
btPairCachingGhostObject расширяет функциональность
базового ghost-объекта:
btKinematicCharacterController).Внутренне использует pair cache, интегрированный в broadphase.
const ghostObject = new Ammo.btPairCachingGhostObject();
ghostObject.setCollisionShape(shape);
ghostObject.setWorldTransform(transform);
Добавление в мир выполняется аналогично
btGhostObject.
В broadphase каждый объект регистрируется через
btBroadphaseProxy. btPairCachingGhostObject
хранит btHashedOverlappingPairCache, позволяющий:
Это особенно важно в:
Ghost-объекты требуют установки специального флага:
ghostObject.setCollisionFlags(
ghostObject.getCollisionFlags() |
Ammo.btCollisionObject.CF_NO_CONTACT_RESPONSE
);
Флаг CF_NO_CONTACT_RESPONSE гарантирует отсутствие
физического отклика.
Дополнительно может применяться:
CF_CHARACTER_OBJECT — для объектов персонажей.const triggerShape = new Ammo.btBoxShape(
new Ammo.btVector3(5, 2, 5)
);
const trigger = new Ammo.btGhostObject();
trigger.setCollisionShape(triggerShape);
trigger.setWorldTransform(transform);
trigger.setCollisionFlags(
trigger.getCollisionFlags() |
Ammo.btCollisionObject.CF_NO_CONTACT_RESPONSE
);
physicsWorld.addCollisionObject(
trigger,
1,
-1
);
const count = trigger.getNumOverlappingObjects();
if (count > 0) {
// объект внутри зоны
}
В связке с btKinematicCharacterController применяется
btPairCachingGhostObject. Причины:
Типичная архитектура:
btPairCachingGhostObject
↓
btConvexShape
↓
btKinematicCharacterController
Ghost-объект представляет физическое тело персонажа, а контроллер управляет его перемещением.
| Характеристика | btRigidBody | btGhostObject |
|---|---|---|
| Масса | Есть | Нет |
| Участвует в солвере | Да | Нет |
| Генерирует импульсы | Да | Нет |
| Отслеживает пересечения | Да | Да |
| Используется как триггер | Неудобно | Да |
Rigid body всегда создаёт физическую реакцию. Ghost-объект — только событие пересечения.
Для корректной фильтрации используется битовая маска:
const GROUP_TRIGGER = 1 << 4;
const GROUP_DYNAMIC = 1 << 1;
physicsWorld.addCollisionObject(
ghostObject,
GROUP_TRIGGER,
GROUP_DYNAMIC
);
Это позволяет:
Pair caching снижает нагрузку при сложных сценах.
Ammo.js требует ручного освобождения памяти:
Ammo.destroy(ghostObject);
Ammo.destroy(shape);
Ammo.destroy(transform);
При утечках:
Без флага объект начинает вести себя как обычный collision object и может мешать физике.
Если маска не совпадает с группой других тел, пересечения не будут обнаружены.
Ghost-объект не интегрируется автоматически. При ручном перемещении необходимо обновлять:
ghostObject.setWorldTransform(newTransform);
Можно сравнивать текущий список пересечений с предыдущим кадром и определять:
Ghost-объект определяет нахождение внутри зоны, а raycast уточняет:
Создание ghost-объекта на один кадр позволяет реализовать:
Ghost-объекты используют тот же broadphase, что и остальные тела. Чаще всего применяется:
btDbvtBroadphaseЭто означает, что триггеры не требуют отдельной структуры данных и полностью интегрированы в физический мир.
Ghost-объекты:
Порядок обновления:
btCollisionObject.В btPairCachingGhostObject шаг 4 сопровождается записью
в pair cache.
Ghost-объекты являются фундаментальным инструментом при построении
игровых механик, где требуется обнаружение пересечений без физического
взаимодействия. Правильное использование btGhostObject и
btPairCachingGhostObject позволяет создавать триггерные
зоны, системы персонажей и сложную логику взаимодействия при сохранении
высокой производительности физической сцены.