В библиотеке Ammo.js, ghost-объект представляет собой особый тип физического объекта, который не участвует в динамическом взаимодействии с миром напрямую. Он не испытывает силы гравитации и не сталкивается с другими объектами с физическим отталкиванием. Ghost-объекты чаще всего используются для:
Ghost-объект создается с помощью
btPairCachingGhostObject. Он может иметь коллизионную
форму, такую как btCapsuleShape или
btBoxShape. Например, для персонажа часто используют
капсулу:
const ghostShape = new Ammo.btCapsuleShape(radius, height);
const ghostObject = new Ammo.btPairCachingGhostObject();
ghostObject.setCollisionShape(ghostShape);
ghostObject.setCollisionFlags(Ammo.btCollisionObject.CF_CHARACTER_OBJECT);
Флаг CF_CHARACTER_OBJECT сообщает физическому движку,
что объект предназначен для персонажного контроллера, что позволяет
корректно обрабатывать столкновения и триггерные события.
Ghost-объект должен быть правильно настроен для взаимодействия с другими объектами сцены. В Ammo.js это делается через маски коллизий:
const collisionGroup = 2; // группа персонажей
const collisionMask = 1 | 4; // взаимодействует с мирами и объектами, но игнорирует триггеры
dynamicsWorld.addCollisionObject(ghostObject, collisionGroup, collisionMask);
Правильная настройка масок позволяет избежать нежелательных столкновений с триггерами или объектами, с которыми персонаж не должен взаимодействовать.
Движение персонажа на основе ghost-объекта не зависит от применения силы, а реализуется через прямую установку позиции и вычисление столкновений. Стандартный подход включает следующие шаги:
convexSweepTest или анализа пересечений с помощью
getOverlappingPairs().Пример базового смещения по оси X/Z:
function moveCharacter(ghostObject, displacement, world) {
const transform = ghostObject.getWorldTransform();
const origin = transform.getOrigin();
const newOrigin = new Ammo.btVector3(
origin.x() + displacement.x,
origin.y() + displacement.y,
origin.z() + displacement.z
);
transform.setOrigin(newOrigin);
ghostObject.setWorldTransform(transform);
}
Ghost-объект автоматически хранит список объектов, с которыми он пересекается, через методы:
const overlappingObjects = ghostObject.getOverlappingPairs();
for (let i = 0; i < overlappingObjects.size(); i++) {
const obj = overlappingObjects.at(i);
// обработка события пересечения
}
Это позволяет реализовать триггеры, подъем по лестницам, зоны урона, сбор предметов и другие элементы взаимодействия без необходимости сложной физики.
Хотя ghost-объект не подчиняется физике напрямую, для имитации прыжка или падения можно использовать вспомогательные параметры:
verticalVelocity,gravity,getOverlappingPairs().Пример применения вертикальной скорости:
if (isOnGround) {
verticalVelocity = jumpSpeed;
} else {
verticalVelocity -= gravity * deltaTime;
}
moveCharacter(ghostObject, { x: 0, y: verticalVelocity * deltaTime, z: 0 }, world);
isOnGround определяется через проверку пересечений с
поверхностями, которые считаются землей.
Для корректной работы ghost-объекта в Ammo.js он должен быть добавлен в мир с динамическим обновлением:
dynamicsWorld.addCollisionObject(ghostObject,
collisionGroup,
collisionMask);
Для каждого кадра необходимо:
convexSweepTest при быстром перемещении
персонажа, чтобы избежать прохождения сквозь тонкие объекты.Ghost-объект в Ammo.js обеспечивает оптимальную основу для персонажного контроллера: точное управление, проверку столкновений и гибкость при взаимодействии с окружением, без необходимости симулировать полную физику персонажа.