В механизме 2D-физики, как я могу избежать бесполезного разрешения столкновений, когда объекты останавливаются?

9

В физическом движке, который я разрабатываю (для обучения) с использованием love-2d , я реализовал разрешение столкновений следующим образом:

FixedUpdate(dt)  // I use fixed timestep
 foreach collide c1 in allNotStaticColliders
   c1.integartePhysic // i.e. apply gravitational force..
   foreach collider c2 "near" c1 // "near"= I use spatial hashing 
      if collide(c1,c2)
        resolve collision (c1,c2)  // the heavy operation
        collison callbacks c1
        collison callbacks c2
        ...

анимация падения и посадки объектов до остановки

Как вы можете видеть в конце анимации gif, происходит затухание FPS, когда все коллайдеры почти заземлены на статический объект.

конечное статическое состояние, с 2 FPS

Это связано с тем, что количество разрешений столкновений растет, поскольку объекты проводят больше времени, касаясь их при установлении. Тем не менее, многие из расчетов «бесполезны», потому что объекты уже установились в устойчивых положениях друг против друга.

Какова лучшая практика (надеюсь, не требующая степени физики), чтобы избежать этих «бесполезных» обнаружений столкновений?

Редактировать: принимал DMGгоряди намеки и приходи к этому результату (пока не оптимально)

введите описание изображения здесь

(Красный = статический, синий = активный, зеленый = спящий)

dnk drone.vs.drones
источник
1
Обычный подход заключается в том, чтобы «спать» объектам, которые приходят в состояние покоя, и не учитывать взаимодействия между спящими / статическими объектами (но спящий объект все еще может быть разбужен взаимодействием динамического объекта, который все еще активен и движется). К сожалению, это помогает только тогда, когда объект полностью отдыхает. Если я правильно читаю ваш пример, похоже, что ваши проблемы с производительностью начинаются, когда объекты все еще успокаиваются и слегка двигаются. Все, что я могу здесь сделать, это добавить больше трения / демпфирования в систему (возможно, с порогом скорости), чтобы небольшие движения быстрее переходили в истинный отдых.
DMGregory
@DMGregory Звучит как хороший ответ. Добавить это?
Анко

Ответы:

9

Я подозревал, что OP уже знал этот подход, поэтому я упомянул об этом в комментарии как просто отправную точку, но я попытаюсь изложить это немного подробнее ...

Большинство физических движков делят динамические объекты на две группы: « бодрствующий » и « спящий ».

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

А спящая объект ведет себя как статический объект в большинстве отношений - его движение не интегрируется с течением времени (потому что в состоянии покоя, поэтому он не имеет никакого движения) и игнорирует двигатель столкновений между объектами, которые спят или статическим.

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

Таким образом, необходимо проверять только столкновения, в которых участвует хотя бы один динамический объект:

Collisions    Static          Sleeping           Awake
          ------------------------------------------------
Awake     |    Check        Check & Wake         Check
Sleeping  |     No               No
Static    |     No

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

Сон помогает только тогда, когда объекты достигают покоя, хотя это может занять некоторое время.

Некоторые вещи, которые вы можете сделать, чтобы быстрее отдохнуть:

  • Имейте ненулевую минимальную скорость или импульс, и зафиксируйте все, что падает ниже его, до нуля. (Это в основном эпсилон, обычно используемый при сравнении поплавков)

  • Используйте трение, демпфирование и неупругие столкновения, чтобы откачать энергию из системы и помочь ей быстрее достичь покоя.

  • Избирательно увеличивайте трение / демпфирование / неупругость для медленно движущихся объектов, чтобы дать им последний толчок к отдыху, не влияя на поведение более энергичных тел.

ДМГригорий
источник
Хороший ответ. Вы указываете на множество хороших идей. Для проверки сна / бодрствования я вижу 2 слабых места: 1) если спящий объект o1 под спящим объектом o2 пробуждается, удаляясь от o2, он не пробуждается o2; 2) если я уберу статическую платформу под спящий объект, этот объект не проснется (под действием силы тяжести)
dnk drone.vs.drones
1
@ dnkdrone.vs.drones Хорошие наблюдения. Никогда сам не писал физический движок, я не уверен, как с этим обычно справляются. Одна из возможностей заключается в том, что при переводе объекта в спящий режим мы сохраняем список объектов, к которым он прикасается (или добавляем его в локальный кластер объектов). Когда мы разбудим спящий объект, мы также разбудим все в его списке / кластере. Могут быть более элегантные варианты, такие как проверка ближайших контактов в момент пробуждения (до того, как он будет удален).
DMGregory