Kinematic character controller (KCC) в Ammo.js представляет собой компонент управления персонажем, который работает на основе кинематической модели вместо динамической. В отличие от обычных rigid body, кинематический контроллер не подчиняется полностью физическим силам, таким как гравитация или столкновения с другими объектами, а позволяет напрямую задавать положение и движение персонажа. Это особенно важно для игр, где необходимо контролировать точное перемещение и взаимодействие с окружением без эффекта «шарика, катящегося по наклонной поверхности».
KCC реализуется через комбинацию
btKinematicCharacterController и вспомогательных
коллизионных объектов, обычно btConvexShape, таких как
капсула (btCapsuleShape). Важная особенность: контроллер
сам управляет коллизиями, используя встроенный ghost
object (btPairCachingGhostObject), который
фиксирует столкновения с другими физическими телами, но не влияет на их
физическое состояние.
Для создания кинематического персонажа необходимо выполнить несколько шагов:
const capsuleHeight = 1.8;
const capsuleRadius = 0.3;
const capsuleShape = new Ammo.btCapsuleShape(capsuleRadius, capsuleHeight);
const ghostObject = new Ammo.btPairCachingGhostObject();
const startTransform = new Ammo.btTransform();
startTransform.setIdentity();
startTransform.setOrigin(new Ammo.btVector3(0, capsuleHeight / 2, 0));
ghostObject.setWorldTransform(startTransform);
ghostObject.setCollisionShape(capsuleShape);
ghostObject.setCollisionFlags(Ammo.cf_kinematic_object | Ammo.cf_character_object);
Ghost object позволяет контроллеру отслеживать столкновения без
воздействия на физические объекты сцены. Флаги
cf_kinematic_object и cf_character_object
критичны для корректной работы контроллера.
const stepHeight = 0.35;
const characterController = new Ammo.btKinematicCharacterController(ghostObject, capsuleShape, stepHeight);
physicsWorld.addAction(characterController);
stepHeight определяет максимальную высоту препятствия,
через которое персонаж может «перешагнуть». Это важно для естественного
движения по сцене с лестницами или небольшими бордюрами.
btKinematicCharacterController предоставляет набор методов для перемещения и управления состоянием персонажа:
setWalkDirection(btVector3): задаёт направление
движения с учётом времени симуляции. Персонаж двигается плавно, обходя
коллизии.setVelocityForTimeInterval(btVector3, float): задаёт
скорость на определённый промежуток времени. Полезно для реализации
ускорений или рывков.jump(): инициирует прыжок. Контроллер автоматически
учитывает высоту прыжка и гравитацию.onGround(): возвращает true, если персонаж находится на
поверхности. Используется для ограничения возможности прыжка только с
земли.setMaxSlope(float): задаёт максимальный угол наклона
поверхности, на которой персонаж может стоять.Пример перемещения:
const direction = new Ammo.btVector3(1, 0, 0);
characterController.setWalkDirection(direction.op_mul(deltaTime));
Метод op_mul используется для масштабирования вектора на
время кадра, чтобы движение было плавным и независимым от FPS.
Контроллер работает через ghost object, который накапливает все объекты, с которыми было взаимодействие. Для получения информации о коллизиях применяются методы:
const numOverlaps = ghostObject.getNumOverlappingObjects();
for (let i = 0; i < numOverlaps; i++) {
const overlappingObject = ghostObject.getOverlappingObject(i);
// Обработка столкновения
}
Важно понимать, что KCC не влияет на столкнувшиеся объекты физически. Для реакции объектов на столкновения необходимо отдельно управлять rigid bodies сцены.
Хотя KCC сам не является динамическим телом, он учитывает гравитацию
через setGravity:
characterController.setGravity(new Ammo.btVector3(0, -9.8, 0));
Параметр jumpSpeed регулирует высоту прыжка:
characterController.setJumpSpeed(10);
Комбинация этих настроек позволяет создавать реалистичные движения персонажа: естественные прыжки, падения и шаги по наклонной поверхности.
setWalkDirection
или setVelocityForTimeInterval. Прямое изменение
трансформации ghost object может вызвать некорректные коллизии.stepHeight,
maxSlope и гравитацию.KCC требует регулярного обновления в цикле симуляции:
function updatePhysics(deltaTime) {
// Обновление контроллера
const walkDir = computeDirection();
characterController.setWalkDirection(walkDir.op_mul(deltaTime));
physicsWorld.stepSimulation(deltaTime, 10);
}
computeDirection() формирует вектор движения на основе
пользовательского ввода или AI. Важно, чтобы stepSimulation
выполнялся после задания направления движения для корректного
взаимодействия с миром.
KCC на базе Ammo.js широко используется для:
Использование btKinematicCharacterController обеспечивает баланс между управляемостью персонажа и физической реалистичностью взаимодействия с окружением. Он позволяет реализовать плавные движения, прыжки, скольжение по склонам и безопасное преодоление препятствий, сохраняя при этом стабильность симуляции.