Очистка и уничтожение мира

В Oimo.js физический мир представлен объектом OIMO.World. Создание мира начинается с вызова конструктора:

const world = new OIMO.World({
    timestep: 1/60,
    iterations: 8,
    broadphase: 2,
    worldscale: 1,
    random: true,
    info: false
});
  • timestep — шаг интеграции в секундах. Стандартное значение 1/60 соответствует 60 кадрам в секунду.
  • iterations — число итераций для расчета столкновений. Увеличение повышает точность, но снижает производительность.
  • broadphase — алгоритм обнаружения потенциальных столкновений (0 — brute-force, 1 — sweep and prune, 2 — grid).
  • worldscale — масштабирование мира. Позволяет работать с объектами разных размеров, корректируя числовые значения сил и масс.
  • random — использование случайного распределения для инициализации внутренней структуры.
  • info — вывод дополнительной информации для отладки.

После создания мира добавляются тела и соединения, которые управляют физикой объектов.

Очистка мира

Очистка мира в Oimo.js необходима для корректного завершения симуляции или подготовки к новой сцене. Важно различать удаление тел и уничтожение самого мира.

Удаление всех тел

Каждое тело хранится в массиве world.bodies. Чтобы удалить все тела, выполняется итерация:

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

Особенности:

  • Итерация ведется с конца массива, чтобы избежать проблем с индексами при удалении элементов.
  • removeRigidBody корректно удаляет тело и все связанные с ним соединения (joints).
  • В случае сложных сцен, где тела связаны через несколько соединений, рекомендуется сначала удалить все соединения, чтобы избежать dangling-ссылок:
for (let joint of world.joints) {
    world.removeJoint(joint);
}

Сброс внутренних структур

После удаления тел и соединений стоит вызвать внутренние методы очистки, если они доступны, или создать новый объект мира. В стандартной версии Oimo.js явного метода world.clear() нет, поэтому практика обычно следующая:

world = new OIMO.World({
    timestep: 1/60,
    iterations: 8,
    broadphase: 2
});

Создание нового мира гарантирует полное освобождение памяти, удаление всех тел, соединений и оптимизационных структур broadphase.

Уничтожение мира

Прямое уничтожение мира подразумевает освобождение всех ресурсов и прекращение симуляции. Oimo.js не предоставляет метод destroy() для объектов World, но можно выполнить следующие действия:

  1. Удаление всех тел и соединений (как показано выше).
  2. Обнуление ссылок на объекты:
world.bodies.length = 0;
world.joints.length = 0;
world = null;
  1. Очистка пользовательских данных — если к телам были прикреплены дополнительные объекты (mesh, userdata), их также следует удалить, чтобы избежать утечек памяти.

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

  • Oimo.js использует внутренние массивы для ускорения обработки столкновений. Даже после удаления тел могут оставаться пустые элементы в массивах. Полное уничтожение мира с последующим созданием нового объекта минимизирует фрагментацию памяти.
  • Ссылки на тела из других частей программы необходимо обнулить вручную. Любая живая ссылка на RigidBody предотвратит сборку мусора.
  • Для динамических сцен с постоянной сменой объектов рекомендуется повторное создание мира вместо последовательного удаления тел. Это обеспечивает стабильную производительность и предотвращает накопление мусора.

Практические советы

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

Итоговая схема очистки

  1. Удаление всех соединений: world.removeJoint(joint).
  2. Удаление всех тел: world.removeRigidBody(body).
  3. Обнуление ссылок: world = null.
  4. Создание нового мира для новой сцены.

Этот подход гарантирует корректное завершение симуляции, предотвращает утечки памяти и обеспечивает стабильность работы Oimo.js в сложных проектах с множеством объектов.