Як у 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

Це пояснюється тим, що кількість дозволів зіткнення зростає, коли об’єкти проводять більше часу, торкаючись, коли вони осідають. Однак багато з обчислень є "марними", оскільки об'єкти вже осіли у стійких положеннях один проти одного.

Яка найкраща практика (сподіваємось, що не вимагає ступеня фізики), щоб уникнути цих "марних" виявлень зіткнень?

Редагувати: прийняті підказки DMGregory та прийти до цього результату (ще не оптимально)

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

(Червоний = статичний, синій = активний, зелений = сплячий)


1
Звичайний підхід полягає в тому, щоб "спати" об'єкти, які перебувають у спокої, і не враховувати взаємодії між сплячими / статичними об'єктами (але сплячий об'єкт все ще може бути пробуджений взаємодією динамічного об'єкта, який все ще прокидається і рухається). На жаль, це допомагає лише коли об'єкт повністю знаходиться в спокої. Якщо я правильно читаю ваш приклад, виглядає так, що ваші проблеми з продуктивністю починаються, коли об’єкти все ще розташовуються і трохи рухаються. Все, що я можу зробити тут, - це додавати більше тертя / демпфування в систему (можливо, з порогом швидкості), щоб невеликі рухи швидко розпадалися на справжній спокій.
DMGregory

@DMGregory Це здається гарною відповіддю. Додати?
Анко

Відповіді:


9

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

Більшість двигунів фізики поділяють динамічні об'єкти на дві групи: « неспані » та « сплячі ».

Об'єкти сплять, коли сидять у спокої, і прокидаються, коли рухаються або прискорюються деяким зовнішнім впливом.

А спляча об'єкт поводиться як статичний об'єкт в більшості відносин - його рух не інтегрується з плином часу (тому що в стані спокою, тому він не має ніякого руху) і ігнорує двигун зіткнень між об'єктами, які сплять або статичним.

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

Отже, потрібно перевіряти лише зіткнення, що включають хоча б один динамічний об'єкт, що прокидається:

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

Це може різко зменшити кількість об'єктів, які потребують активного моделювання, особливо в палі, які, як показано в запитанні, мають багато взаємних зіткнень, щоб перевірити, чи не рухається сітка.

Сон допомагає лише після того, як об'єкти дійсно дістають спокою, але це може зайняти деякий час.

Деякі речі, які ви можете зробити, щоб швидше відпочити:

  • Майте ненульову мінімальну швидкість або імпульс і затискайте все, що опускається нижче неї, до нуля. (В основному це епсілон, який зазвичай використовується для порівняння поплавців)

  • Використовуйте тертя, демпфірування та нееластичні зіткнення, щоб витягти енергію із системи та допомогти їй швидше відпочити в цілому.

  • Вибірково збільшуйте тертя / демпфірування / нееластичність для об'єктів, що рухаються повільно, щоб дати їм остаточне натискання на відпочинок, не впливаючи на поведінку більш енергійних тіл.


Хороша відповідь. Ви вказуєте купу хороших ідей. Для перевірки сну / неспання я бачу 2 слабкі моменти: 1) якщо сплячий предмет o1 під сплячим обжетом o2 пробуджується від о2, він не прокидається o2; 2) якщо я
видаляю

1
@ dnkdrone.vs.drones Хороші спостереження. Ніколи не писав сам двигун фізики, я не впевнений, як це нормально обробляється. Однією з можливостей є те, що при встановленні об'єкта для сну ми зберігаємо список об’єктів, до яких він торкається (або додаємо його до локального кластеру об’єктів). Коли ми розбуджуємо сплячий об’єкт, ми також прокидаємо все в його списку / кластері. Можуть бути і більш елегантні варіанти, як-от перевірка наявності сусідніх контактів у момент пробудження (перед тим, як його перенести).
DMGregory
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.