Удаление тела из мира

В Oimo.js объекты физического мира представлены экземплярами класса Oimo.Body, которые добавляются в физический мир через Oimo.World. Для корректного удаления тела из симуляции требуется учитывать внутренние структуры движка и ссылки на тело, чтобы избежать утечек памяти и ошибок во время шага симуляции.

Основные методы удаления тела

1. Метод world.removeRigidBody(body)

Каждое тело, добавленное в мир, хранится во внутреннем массиве rigidBodies. Для удаления объекта из мира используется метод:

world.removeRigidBody(body);

Где body — ссылка на удаляемый объект Oimo.Body. После вызова этого метода тело перестает участвовать в расчётах силы, столкновений и интеграции.

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


2. Очистка ссылок на тело

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

body = null;

или удалять тело из собственных массивов и структур данных:

let index = objectsArray.indexOf(body);
if (index !== -1) objectsArray.splice(index, 1);

Это особенно важно при работе с динамическими объектами, создаваемыми в цикле.


Удаление всех тел одновременно

Для сброса мира или удаления всех объектов удобно использовать цикл:

for (let i = world.rigidBodies.length - 1; i >= 0; i--) {
    world.removeRigidBody(world.rigidBodies[i]);
}

Обратный цикл необходим, чтобы корректно удалять элементы из массива, не нарушая индексы.


Особенности удаления при использовании тел с формами

Тела в Oimo.js могут иметь одну или несколько форм (Oimo.Shape), каждая из которых участвует в расчётах столкновений. При удалении тела:

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

Влияние на обработку столкновений

Удаление тела во время расчёта столкновений может вызвать исключения, если движок ещё не завершил обработку текущего шага. Рекомендуется:

  1. Отмечать тела для удаления флагом toRemove.
  2. После завершения текущего шага симуляции пройтись по массиву и удалить помеченные тела:
world.step(timeStep);
bodies.forEach(body => {
    if (body.toRemove) {
        world.removeRigidBody(body);
    }
});

Такой подход предотвращает ошибки в обработке коллизий и интеграции.


Практические рекомендации

  • Никогда не модифицировать массив rigidBodies напрямую во время шага симуляции.
  • Для динамических сцен, где тела создаются и удаляются часто, хранить объекты в отдельной структуре для удобного контроля.
  • Удаление тел нужно сопровождать очисткой пользовательских данных, например, визуальных представлений (Three.js Mesh), чтобы не возникало рассинхронизации между графикой и физикой.

Пример полного цикла создания и удаления тела

// Создание тела
let box = world.add({
    type: 'box',
    size: [1, 1, 1],
    pos: [0, 5, 0],
    move: true
});

// Отметка для удаления после 3 секунд
setTimeout(() => {
    box.toRemove = true;
}, 3000);

// Основной цикл
function update() {
    world.step(1/60);
    
    // Удаление помеченных тел
    world.rigidBodies.forEach(body => {
        if (body.toRemove) {
            world.removeRigidBody(body);
        }
    });

    requestAnimationFrame(update);
}

update();

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

Удаление тел — базовая операция, но правильная организация циклов и очистка ссылок критична для стабильности и производительности больших физико-графических проектов.