Настройка allowSleep для снижения нагрузки

В библиотеке Cannon.js управление состоянием сна (sleep) объектов является одним из ключевых способов снижения нагрузки на физический движок. Свойство allowSleep позволяет объектам временно «засыпать», когда они не участвуют активно в симуляции, что существенно уменьшает количество вычислений.

Основные принципы работы сна

Каждое тело (Body) в Cannon.js обладает параметрами, определяющими его способность входить в состояние сна:

  • allowSleep – булево значение, указывающее, разрешено ли телу переходить в сон. По умолчанию false.
  • sleepSpeedLimit – порог линейной и угловой скорости, ниже которого тело считается неподвижным.
  • sleepTimeLimit – время, в течение которого тело должно оставаться неподвижным для входа в сон.

Когда тело удовлетворяет условиям sleepSpeedLimit и sleepTimeLimit, движок переводит его в состояние сна. Сон предотвращает дальнейшие расчеты для этого тела до момента, когда на него воздействует сила или происходит столкновение.

Настройка allowSleep

const body = new CANNON.Body({
    mass: 5,
    shape: new CANNON.Sphere(1),
    allowSleep: true
});

body.sleepSpeedLimit = 0.1; // минимальная скорость для сна
body.sleepTimeLimit = 1.0;  // время в секундах до сна

Ключевые моменты настройки:

  • allowSleep обязательно должно быть true, иначе тело никогда не «уснет».
  • sleepSpeedLimit не должен быть слишком высоким, иначе объекты будут входить в сон преждевременно и поведение симуляции станет неестественным.
  • sleepTimeLimit определяет устойчивость состояния сна. Меньшие значения ускоряют сон, большие – делают симуляцию более плавной.

Влияние на производительность

В крупных сценах с множеством объектов включение allowSleep может снизить нагрузку на CPU до 30–50%, так как:

  1. Тела в состоянии сна не участвуют в расчете столкновений и интеграции движения.
  2. Движок проверяет скорость и время неподвижности только периодически, а не на каждом кадре.
  3. Количество активных тел уменьшается, что снижает сложность O(n²) расчета столкновений.

Пример динамической сцены:

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

for (let i = 0; i < 100; i++) {
    const box = new CANNON.Body({
        mass: 1,
        shape: new CANNON.Box(new CANNON.Vec3(0.5, 0.5, 0.5)),
        allowSleep: true
    });
    box.position.set(Math.random() * 10, 10 + i, Math.random() * 10);
    box.sleepSpeedLimit = 0.05;
    box.sleepTimeLimit = 0.5;
    world.addBody(box);
}

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

Принципы пробуждения объектов

Объекты выходят из сна автоматически при:

  • Применении силы или импульса (applyForce, applyImpulse).
  • Столкновении с активным телом.
box.applyForce(new CANNON.Vec3(0, 10, 0), box.position);

После этого тело сразу становится активным и снова участвует в расчетах столкновений и интеграции движения.

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

  • Для статических и редко перемещающихся объектов всегда использовать allowSleep: true.
  • Для динамичных объектов, участвующих в постоянных столкновениях, включение сна может быть менее эффективным.
  • Настройка sleepSpeedLimit должна учитывать размеры и массу объектов: крупные тяжёлые тела требуют меньшей чувствительности к скорости для сна.
  • В комбинации с step мироустановки оптимизация сна позволяет плавно масштабировать сцену до сотен объектов без значительной потери производительности.

Взаимодействие с другими параметрами мира

  • world.broadphase – использование продвинутого широкофазного алгоритма (SAPBroadphase) в сочетании с allowSleep позволяет ещё больше уменьшить нагрузку.
  • solver.iterations – меньшее количество итераций решателя совместимо с объектами в состоянии сна, поскольку активных контактов меньше.
  • timeStep – увеличение шага интеграции (fixedTimeStep) с объектами, которые могут уснуть, снижает частоту обновлений без видимых артефактов.

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