Zdarzenie Unity dotyczące kolizji daje ci obiekt kolizji, który daje pewne informacje na temat kolizji, która miała miejsce (w tym listę punktów kontaktowych z normalnymi trafieniami).
Ale nie dostajesz normalnych powierzchni dla zderzacza, który trafiłeś. Oto zrzut ekranu do zilustrowania. Czerwona linia pochodzi z, ContactPoint.normal
a niebieska linia pochodzi z RaycastHit.normal
.
Czy jest to przykład ukrywania informacji w Unity w celu zapewnienia uproszczonego interfejsu API? A może standardowe techniki wykrywania kolizji w czasie rzeczywistym 3D po prostu nie zbierają tych informacji?
A jeśli chodzi o drugą część pytania, jaki jest pewny i stosunkowo skuteczny sposób na uzyskanie normalnej powierzchni na wypadek kolizji?
Wiem, że raycasting daje ci normalne na powierzchni, ale wydaje się, że muszę zrobić kilka raycastów, aby osiągnąć to we wszystkich scenariuszach (może punkt kontaktowy / normalna kombinacja nie trafia w zderzacz przy pierwszym rzucie, a może musisz zrobić jakąś średnią ze wszystkich normalne punkty kontaktowe, aby uzyskać najlepszy wynik).
Moja obecna metoda:
Wykonaj kopię zapasową
Collision.contacts[0].point
wzdłuż jej normalnego poziomuRaycast w dół zanegowane trafienie normalne
float.MaxValue
, naCollision.collider
Jeśli to się nie powiedzie, powtórz kroki 1 i 2 z niez negowanym normalnym
Jeśli to się nie powiedzie, spróbuj wykonać kroki od 1 do 3 za pomocą
Collision.contacts[1]
Powtarzaj 4, aż się powiedzie lub do wyczerpania wszystkich punktów kontaktowych.
Poddaj się, wróć
Vector3.zero
.
Wydaje się, że to wszystko łapie, ale wszystkie te raycaste powodują, że mam mdłości i nie jestem pewien, jak sprawdzić, czy działa to w wystarczającej liczbie przypadków. Czy jest lepszy sposób?
EDYCJA Jeśli tak właśnie jest z kolizją 3D, przegląd tego, dlaczego w ogólnym przypadku byłby tak samo mile widziany, jak coś specyficznego dla Unity.
źródło
Odpowiedzi:
Tak naprawdę dzieje się tak w przypadku kolizji. Nie tylko 3D, ale także 2D. Weź następujący przykład:
Zielone i czerwone AABB zderzają się, a kolektor stykowy to niebieski obszar. Punkty kontaktowe będą znajdować się gdzieś w niebieskim obszarze (dokładnie gdzie może się różnić w zależności od algorytmu, ale rogi, w których spotykają się niebieski / czerwony / zielony, są idealne).
Jaką normalną powierzchnię należy zwrócić? Górna krawędź czerwonego AABB czy lewa krawędź? Jeśli spadnie zielone pole, być może uda nam się odgadnąć górną krawędź. jeśli porusza się w prawo, być może uda nam się odgadnąć lewą krawędź. Co jeśli poruszał się w dół i dobrze? Czy przyjmujemy oś najmniejszej penetracji? Oś prędkości największej prędkości? Jakaś heurystyka obu? Co by było, gdyby pudła zderzyły się dokładnie na rogach?
Rozszerz to na złożoną powierzchnię 3D potencjalnie złożoną z setek tris / ścian. Nadal będziesz mieć tylko niewielką liczbę idealnych punktów kontaktowych. Jaką normalną powierzchnię należy zwrócić? Czy średnia normalna powierzchnia na całej siatce trójsiatkowej (co nie ma sensu dla większości obiektów)? Punkty bezpośrednio „pod” rogami kolizji (które nie są dobrze zdefiniowane dla większości innych kształtów)? Czy próbujesz znaleźć najbliższą powierzchnię do wygenerowanych punktów kontaktowych (co wymagałoby drugiego przejścia, ponieważ punkty kontaktowe nie są obliczane bezpośrednio z żadnych ścian siatki)? Jeśli znajdziesz najbliższą twarz, czy bierzesz normalną twarz, czy interpolujesz jej wierzchołki w punkcie styku, aby uzyskać prawidłową normalną dla „gładkich” obiektów?
Naprawdę głównym problemem jest to, że punkty kontaktowe nie są wszystkimi punktami kontaktowymi. W wielu przypadkach byłby to jednak nieskończony zestaw punktów. To tylko kilka punktów, które są dobrze rozmieszczone, co umożliwia racjonalne przybliżenie reakcji fizycznej poprzez zastosowanie sił w tych punktach, aby popchnąć zderzające się obiekty w sposób realistyczny. Konkretne punkty / lokalizacje faktycznego kontaktu z obiektem są wyodrębnione za uproszczonym modelem matematycznym. Dlatego idea określonej normalnej powierzchni kontaktu po prostu nie ma większego sensu w ogólnym przypadku.
Oczywiście, dzięki bardziej szczegółowym ograniczeniom i ograniczeniom dotyczącym twoich obiektów, świata i ruchu, możesz stworzyć alternatywne algorytmy kolizji, które powiedzą ci o normalnej powierzchni. W powyższym przypadku 2D, jeśli założymy, że pola nigdy się nie obracają i znamy względną prędkość i ostatnią pozycję każdego z nich, mogliby użyć ciągłego wykrywania kolizji, aby dowiedzieć się dokładnie, kiedy się zderzą i które cechy zderzyły się, dostarczając nam dokładna cecha, w której doszło do kolizji, którą można następnie wykorzystać jako kontakt / kolizję / normalną powierzchnię. Gry platformowe są zbudowane w całości na takich założeniach i specjalnych sztuczkach (dlatego użycie ogólnej biblioteki fizyki, takiej jak Box2D lub Havok, lub światło nigdy nie zapewnia takiej ścisłej, precyzyjnej kontroli, jaką można znaleźć w klasycznych platformówkach, takich jak Mario lub Sonic; chcę to powiedzieć
Ogólne biblioteki fizyki newtonowskiej, takie jak te używane w Unity3D, nie mogą robić tego rodzaju uproszczeń i założeń. Dlatego nie otrzymujesz normalnych powierzchni kolizji, dostajesz kolektor kontaktowy, ogólnie uproszczony do punktów kontaktowych i to wszystko.
źródło