W jaki sposób w silniku fizyki 2D mogę uniknąć niepotrzebnych rozwiązań kolizji, gdy obiekty zatrzymują się?

9

W silniku fizyki rozwijam (do nauki) za pomocą love-2d zaimplementowałem rozwiązania kolizji w następujący sposób:

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
        ...

animacja spadających i opadających przedmiotów

Jak widać na końcu animacji gif, następuje zanik FPS, gdy wszystkie zderzaki są prawie uziemione na obiekcie statycznym.

końcowy stan statyczny z 2 FPS

Wynika to z faktu, że liczba rozdzielczości kolizji rośnie, gdy obiekty spędzają więcej czasu na dotykaniu podczas osiadania. Jednak wiele obliczeń jest „bezużytecznych”, ponieważ obiekty już ustabilizowały się względem siebie.

Jaka jest najlepsza praktyka (miejmy nadzieję, że nie wymaga dyplomu fizyki), aby uniknąć tych „bezużytecznych” detekcji kolizji?

Edycja: zaakceptowano wskazówki DMGregory i doszło do tego wyniku (jeszcze nie optymalny)

wprowadź opis zdjęcia tutaj

(Czerwony = statyczny, niebieski = aktywny, zielony = spanie)

dnk drone.vs.drones
źródło
1
Typowym podejściem jest „uśpienie” obiektów, które zatrzymują się, i nie uwzględnianie interakcji między obiektami śpiącymi / statycznymi (ale obiekt uśpiony może być nadal budzony przez interakcję z obiektu dynamicznego, który wciąż nie śpi i porusza się). Niestety pomaga to tylko wtedy, gdy obiekt jest w pełni w spoczynku. Jeśli dobrze czytam twój przykład, wygląda na to, że Twoje problemy z wydajnością zaczynają się, gdy obiekty wciąż się uspokajają i poruszają. Wszystko, co mogę tutaj zrobić, to dodać do systemu więcej tarcia / tłumienia (być może z progiem prędkości), aby małe ruchy szybciej zanikały, aby rzeczywiście odpocząć.
DMGregory
@DMGregory To brzmi jak dobra odpowiedź. Dodać?
Anko

Odpowiedzi:

9

Podejrzewałem, że OP zna takie podejście, więc wspomniałem o tym w komentarzu jako punkcie wyjścia, ale postaram się je rozwinąć jeszcze trochę ...

Większość silników fizycznych dzieli obiekty dynamiczne na dwie grupy: „ przebudź się ” i „ śpij ”.

Przedmioty śpią, gdy siedzą w spoczynku, i budzą się, gdy są poruszane lub przyspieszane przez wpływ z zewnątrz.

Obiekt śpiący pod wieloma względami zachowuje się jak obiekt statyczny - jego ruch nie jest zintegrowany w czasie (ponieważ jest w spoczynku, więc nie ma ruchu), a silnik ignoruje kolizje między obiektami śpiącymi lub statycznymi.

Obiekt do spania siedzący na nieruchomej podłodze nie spada przez niego, pomimo braku reakcji na kolizję, ponieważ cała integracja ruchu jest pomijana dla obiektów do spania, w tym grawitacji.

Tak więc należy sprawdzić tylko kolizje obejmujące co najmniej jeden przebudzony obiekt dynamiczny:

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

Może to radykalnie zmniejszyć liczbę obiektów wymagających aktywnej symulacji, zwłaszcza na stosach, które, jak pokazano w pytaniu, mają wiele wzajemnych kolizji, aby sprawdzić niewielki lub zerowy ruch siatki.

Jednak spanie pomaga tylko wtedy, gdy przedmioty rzeczywiście znajdą się w spoczynku, co może chwilę potrwać.

Niektóre rzeczy, które możesz zrobić, aby szybciej dotrzeć do odpoczynku:

  • Miej niezerową minimalną prędkość lub pęd i ustaw wszystko, co spadnie poniżej zera, na zero. (Jest to w zasadzie epsilon, powszechnie używany do porównywania pływaków)

  • Użyj tarcia, tłumienia i nieelastycznych kolizji, aby odsysać energię z systemu i pomóc mu szybciej dotrzeć do spoczynku.

  • Zwiększ tarcie / tłumienie / nieelastyczność wybiórczo dla wolno poruszających się obiektów, aby dać im ostateczny impuls do odpoczynku, bez wpływu na zachowanie bardziej energetycznych ciał.

DMGregory
źródło
Dobra odpowiedź. Wskazuje się na szereg dobrych pomysłów. Do kontroli snu / przebudzenia widzę 2 słabe punkty: 1) jeśli obiekt spania o1 pod śpiącym objet o2 budzi się odsuwając od o2, nie budzi się o2; 2) jeśli
usunę
1
@ dnkdrone.vs.drones Dobre obserwacje. Nigdy nie napisałem silnika fizyki, ale nie jestem pewien, jak normalnie jest to obsługiwane. Jedną z możliwości jest to, że ustawiając obiekt w tryb uśpienia, przechowujemy listę obiektów, których dotyka (lub dodajemy go do lokalnej grupy obiektów). Kiedy budzimy uśpiony obiekt, budzimy również wszystko z jego listy / klastra. Mogą istnieć bardziej eleganckie opcje, takie jak sprawdzanie pobliskich kontaktów w momencie przebudzenia (przed przeniesieniem).
DMGregory