Ignoruj ​​kolizje z niektórymi obiektami w określonych kontekstach

14

Robię grę wyścigową z samochodami w Unity. Samochód ma doładowanie / wzmocnienie nitro. Podczas wzmacniania nie chciałbym być zboczony podczas zderzenia z zombie, ale chcę być zboczony podczas zderzenia ze ścianami.

Z drugiej strony nie chcę ignorować kolizji z zombie, ponieważ nadal chcę je uderzać przy uderzeniu.

Jak mam sobie z tym poradzić? Zasadniczo chcę, aby samochód nie obracał się podczas zderzenia z niektórymi przedmiotami.

Paul Manta
źródło

Odpowiedzi:

7

Rozważ manipulowanie warstwami w czasie wykonywania.

Włączanie / wyłączanie kolizji dla niektórych obiektów z całymi warstwami

Physics.IgnoreCollision i Physics.IgnoreLayerCollision umożliwiają wyłączenie kolizji odpowiednio między dwoma zderzaczami i między dwiema warstwami.

Jeśli chcesz wykluczyć konkretny zderzacz z kolizji, nie ma wbudowanego sposobu, aby to zrobić. Jeśli używasz sztywnych obiektów nie kinematycznych z zderzaczami nie wyzwalającymi, zawsze będzie odpowiedź, nawet jeśli spróbujesz odfiltrować odpowiedzi według znacznika.

Sposób, w jaki osiągnęliśmy to w naszym projekcie, polegał na stworzeniu warstwy o nazwie „Void”. Pustka w ogóle się nie koliduje.

Teraz możesz tymczasowo wyłączyć kolizję zderzacza, ustawiając jego warstwę na „Void” i włącz ją ponownie, przywracając starą warstwę.

Oto sedno:

int oldLayer = -1;
int voidLayer;

void Start()
{
    voidLayer = LayerMask.NameToLayer("Void");
}

void DisableCollider(Collider col)
{
    oldLayer = col.gameObject.layer;
    col.gameObject.layer = voidLayer;
}

void EnableCollider(Collider col)
{
    col.gameObject.layer = oldLayer;
}

Zrobiliśmy to w szczególności, ponieważ włączanie i wyłączanie zderzaczy, które były dziećmi sztywnych nadwozi, może naprawdę popsuć pewne rzeczy w pewnych okolicznościach. Nie można więc niezawodnie wyłączyć części złożonego zderzaka sztywnego, ale można niezawodnie zamieniać warstwę jednej z części zderzaka złożonego.

Teraz twoja konkretna sytuacja

Aby zmniejszyć wpływ zderzenia zombie na twój samochód, zastanów się nad uruchomieniem kinematycznych zombie sztywnych nadwozi lub w inny sposób zmniejszeniem ich masy (np. Float.Epsilon), aby uderzenie nie miało wpływu na pęd samochodu. Przy uderzeniu możesz również dokonać zmiany warstwy, aby kolejne zderzenia nie były wywoływane, nawet jeśli pierwsza z nich przyłoży niewielką siłę do karoserii samochodu.

Możesz nawet zmienić je na warstwę, która po prostu nie koliduje z samochodem.

Możesz także umieścić kolejny zderzacz na zombie, które aktywują się po przejechaniu. W ten sposób możesz sfałszować siły uderzenia OnTriggerEnter. Nie możesz być z nim tak dokładny, ale możesz oszacować, gdzie normalne styki mogły być wystarczająco dobre, aby rzucić zombie gdzieś zabawnie.

Musisz zadać sobie pytanie:

  • Czy chcę mieć możliwość przewrócenia przejeżdżających zombie moim samochodem, czy powinny po prostu odtworzyć animację śmierci?

  • Czy obchodzi mnie, czy uderzenie zombie w mniejszy sposób wpływa na prędkość samochodu i prędkość kątową?

michael.bartnett
źródło
1

Wywołaj Physics.IgnoreCollision na wszystkich zombie, przekazując funkcję obiektowi gracza, gdy samochód zacznie przyspieszać. Spowoduje to, że Unity nie będzie reagować na kolizje między graczem a zombie. Kiedy samochód skończy doładowywać, zadzwoń Physics.IgnoreCollisionponownie do każdego zombie, przekazując mu obiekt gracza i falseaby ponownie uruchomić reakcję na kolizję.

Wackidev
źródło
Oznaczałoby to jednak, że nie zderzą się z niczym innym.
Paul Manta
Zrobię więcej badań. Jedyne, co mogę wymyślić, to: być może możesz zignorować kolizję, zwracając wartość false z OnCollisionEnter?
Wackidev
@Wackidev Tak nie jest.
Rhys van der Waerden,
@Paul Zredagowałem swoją odpowiedź.
Wackidev
0

Zgaduję, że możesz sprawdzić nazwy obiektów lub dodać wartość nazwy do klas obiektów, a następnie to sprawdzić?

bool boosting = false; //need a trigger in the game to set this to true.

function OnCollisionEnter(theCollision : Collision)
{   
    if (boosting == true)
    {
        if(theCollision.gameObject.name == "Zombie")
        {
              Debug.Log("Zombie hit during boost");              
        }
        else if(theCollision.gameObject.name == "Wall")
        {
              Debug.Log("Wall hit during boost");            
        }
    }
    else 
    {
        if(theCollision.gameObject.name == "Zombie")
        {
              Debug.Log("Zombie hit not in boost");              
        }
        else if(theCollision.gameObject.name == "Wall")
        {
              Debug.Log("Wall hit not in boost");                
        }
    }
}

Następnie wystarczy mieć inną zmienną, której można użyć do sprawdzenia wzmocnienia i dodać ją do czeków.

EDYCJA: dodała tę zmienną do.

Chwytak
źródło
Wie, jak być powiadamianym o kolizjach; po prostu nie chce, aby w wyniku tego podjęto jakieś działanie. W niektórych przypadkach chce wyłączyć wbudowaną reakcję na kolizję.
Wackidev
Z pewnością cokolwiek się stanie, gdy nastąpi zderzenie, przechodzi między nawiasami? Nie korzystałem wcześniej z jedności, więc nie wiem, ale w cocos2d, a XNA jest tak zrobione.
Lewis,
W rzeczywistości Unity sam obsługuje kolizje za pośrednictwem PhysX. OnCollisionEnter to tylko metoda powiadamiania; nie jest zaprojektowany do obsługi rzeczywistej reakcji na kolizję.
Wackidev
0

Zakładam, że używasz silnika fizyki do automatycznego wykonywania „odchylenia” na podstawie kształtu / masy, gdy rzeczy się zderzają? w takim przypadku zmień masę swoich zombie na bardzo minimalną wartość i nie wpłyną one na samochód.

ADB
źródło
0

Istnieją tutaj dwie klasy odpowiedzi:

  1. Ignorowanie lub wyłączanie kolizji
    • Te rozwiązania nie rozwiążą problemu, chce, aby zombie latały po trafieniu.
  2. Zmiana masy:
    • To dobre podejście. Nie zapomnij również odpowiednio zmienić bezwładności.
      • Możesz alternatywnie zmienić masę i bezwładność samochodów podczas doładowania (robimy to, aby zmniejszyć wpływ wszystkich nie kinematycznych obiektów na samochód podczas doładowania)
      • Nie powinno to wpływać na drogę lub ściany, zakładając, że są kinematyczne.

Mam nadzieję że to pomoże!

dwuLive
źródło
Dwie z istniejących odpowiedzi sprzed sześciu lat zalecają sugerowane tutaj podejście oparte na masie. Czy jest jakaś nowa strategia, którą chcesz dodać?
DMGregory
Przepraszam, nie jestem jeszcze w stanie głosować i chciałem upewnić się, że Paul Manta nie zostanie wprowadzony w błąd.
dwuLive