Добавление и удаление тел из мира

В Cannon.js мир (World) представляет собой контейнер для физических объектов и взаимодействий между ними. Каждый объект, добавленный в мир, становится частью симуляции и подвергается воздействию гравитации, столкновений и других физических сил. Для управления телами используются методы addBody и removeBody.

const world = new CANNON.World();
world.gravity.set(0, -9.82, 0);

Здесь создается новый мир с гравитацией вдоль оси Y. После создания мира можно добавлять тела и конфигурировать их поведение.


Добавление тел

Создание тела

Тело (Body) в Cannon.js определяется массой, формой (Shape) и положением. Например, создание сферы:

const radius = 1;
const sphereShape = new CANNON.Sphere(radius);
const sphereBody = new CANNON.Body({
    mass: 5,
    position: new CANNON.Vec3(0, 10, 0),
    shape: sphereShape
});

Добавление в мир

Чтобы тело начало участвовать в симуляции, его необходимо добавить в мир:

world.addBody(sphereBody);

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


Удаление тел

Удаление тела из мира необходимо для оптимизации производительности и динамического управления сценой.

world.removeBody(sphereBody);

После удаления тело перестает участвовать в симуляции, но объект Body остается в памяти, его можно повторно добавить в мир.

Особенности удаления:

  • Удаление тела автоматически исключает его из системы столкновений.
  • Если тело связано с другими объектами через Constraint, связи необходимо удалять или обновлять вручную, иначе могут возникнуть ошибки.
  • Удаление тел во время итерации по массиву world.bodies может привести к пропуску элементов, поэтому лучше удалять объекты после завершения шага симуляции.

Массовое управление телами

Для работы с большим количеством тел можно использовать массивы:

const bodies = [];
for (let i = 0; i < 100; i++) {
    const boxShape = new CANNON.Box(new CANNON.Vec3(1, 1, 1));
    const boxBody = new CANNON.Body({ mass: 1, shape: boxShape });
    boxBody.position.set(Math.random() * 10, 20, Math.random() * 10);
    world.addBody(boxBody);
    bodies.push(boxBody);
}

// Удаление всех тел
bodies.forEach(body => world.removeBody(body));

Преимущества такого подхода:

  • Легко управлять группами объектов.
  • Упрощается динамическое добавление и удаление объектов.
  • Позволяет создавать эффекты разрушения или появления объектов в реальном времени.

Динамическая замена тел

Иногда требуется заменить тело на другое без перезапуска симуляции:

  1. Удалить старое тело из мира.
  2. Создать новое тело с нужными свойствами.
  3. Добавить новое тело в мир.
world.removeBody(sphereBody);

const newSphere = new CANNON.Body({
    mass: 10,
    position: new CANNON.Vec3(0, 15, 0),
    shape: new CANNON.Sphere(2)
});

world.addBody(newSphere);

Такой подход применяется для анимации разрушений, смены персонажей или динамического изменения геометрии сцены.


Взаимодействие с шагом симуляции

Добавление и удаление тел напрямую влияет на шаг симуляции:

const timeStep = 1 / 60;

function update() {
    world.step(timeStep);
    requestAnimationFrame(update);
}

update();

Рекомендации при динамических изменениях:

  • Добавлять и удалять тела между шагами симуляции.
  • Проверять наличие связей (Constraint) перед удалением тел.
  • При массовом добавлении тел распределять их по времени для предотвращения резких коллизий.

Управление формами и телами

Каждое тело может иметь одну или несколько форм (Shape). Добавление формы после создания тела не требует пересоздания тела, но нужно учитывать корректное обновление инерции:

const cylinderShape = new CANNON.Cylinder(1, 1, 2, 16);
sphereBody.addShape(cylinderShape, new CANNON.Vec3(0, 2, 0));
sphereBody.updateMassProperties();

Удаление формы не предусмотрено напрямую, поэтому для замены формы чаще используют создание нового тела и замену старого в мире.


Практическая оптимизация

  • Для объектов, которые временно не участвуют в симуляции, лучше использовать removeBody вместо деактивации.
  • Для объектов с одинаковой формой можно использовать клоны формы для снижения потребления памяти.
  • Проверять world.bodies.length после массовых операций для отладки и предотвращения утечек памяти.

Добавление и удаление тел — ключевой механизм динамической симуляции в Cannon.js, позволяющий создавать реалистичные сцены с изменяющейся физикой и оптимизировать производительность.