Ignorieren Sie Kollisionen mit einigen Objekten in bestimmten Kontexten

14

Ich mache ein Rennspiel mit Autos in Unity. Das Auto hat ein Boost / Nitro-Powerup. Beim Boosten möchte ich nicht abgelenkt werden, wenn ich mit Zombies kollidiere, aber ich möchte abgelenkt werden, wenn ich mit Wänden kollidiere.

Andererseits möchte ich Kollisionen mit Zombies nicht ignorieren, weil ich sie trotzdem beim Aufprall treffen möchte.

Wie soll ich damit umgehen? Grundsätzlich möchte ich, dass sich das Auto bei Kollisionen mit bestimmten Objekten nicht dreht.

Paul Manta
quelle

Antworten:

7

Betrachten Sie die Bearbeitung Ihrer Ebenen zur Laufzeit.

Aktivieren / Deaktivieren von Kollisionen für bestimmte Objekte mit ganzen Ebenen

Mit Physics.IgnoreCollision und Physics.IgnoreLayerCollision können Sie Kollisionen zwischen zwei Kollidern bzw. zwischen zwei Ebenen deaktivieren.

Wenn Sie einen bestimmten Collider von Kollisionen ausschließen möchten, gibt es keine eingebaute Möglichkeit, dies zu tun. Wenn Sie nicht kinematische Starrkörper mit nicht auslösenden Kollidern verwenden, wird immer eine Antwort angezeigt, auch wenn Sie versuchen, die Antworten nach Tags herauszufiltern.

Wir haben dies in unserem Projekt erreicht, indem wir eine Ebene mit dem Namen "Void" erstellt haben. Void kollidiert überhaupt nicht mit irgendetwas.

Jetzt können Sie die Kollision eines Colliders vorübergehend deaktivieren, indem Sie die Ebene auf "Void" setzen und sie wieder aktivieren, indem Sie die alte Ebene wiederherstellen.

Hier ist das Wesentliche:

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;
}

Wir haben dies speziell deshalb getan, weil das Aktivieren und Deaktivieren von Collidern, die Kinder von Starrkörpern waren, unter bestimmten Umständen wirklich zu Problemen führen kann. Sie können also einen Teil eines zusammengesetzten Starrkörper-Colliders nicht zuverlässig deaktivieren, sondern den Layer eines der zusammengesetzten Colliderteile zuverlässig vertauschen.

Jetzt deine spezifische Situation

Um die Auswirkungen einer Zombie-Kollision auf Ihr Auto zu verringern, sollten Sie in Betracht ziehen, die kinematischen Starrkörper Ihrer Zombies auszulösen oder ihre Masse auf andere Weise sehr, sehr klein zu machen (wie z. B. float.Epsilon), damit der Aufprall keinen Einfluss auf den Schwung des Autos hat. Beim Aufprall können Sie diesen Ebenenwechsel auch durchführen, damit nachfolgende Kollisionen nicht ausgelöst werden, selbst wenn die erste eine vernachlässigbare Kraft auf die Karosserie ausübt.

Sie können sie sogar auf eine Ebene verschieben, die einfach nicht mit dem Auto kollidiert.

Sie können Zombies, die beim Überfahren aktiviert werden, auch mit einem anderen Collider versehen. Auf diese Weise können Sie Aufprallkräfte OnTriggerEnter vortäuschen. Sie können nicht so genau damit umgehen, aber Sie können schätzen, wo die Kontaktnormalen gut genug waren, um den Zombie irgendwo hin zu werfen, wo es Spaß macht.

Sie müssen sich fragen:

  • Möchte ich in der Lage sein, die überfahrenen Zombies mit meinem Auto herumzuschlagen, oder sollten sie einfach eine Todesanimation abspielen?

  • Interessiert es mich, wenn die Geschwindigkeit und die Winkelgeschwindigkeit des Autos durch das Treffen von Zombies in geringerem Maße beeinflusst werden?

michael.bartnett
quelle
1

Rufen Sie Physics.IgnoreCollision für alle Zombies auf und übergeben Sie die Funktion dem Spielerobjekt , wenn das Auto mit dem Boosten beginnt. Dadurch reagiert Unity nicht auf Kollisionen zwischen dem Spieler und den Zombies. Wenn das Aufladen des Autos beendet ist, rufen Sie Physics.IgnoreCollisionerneut nach jedem Zombie und übergeben Sie ihm das Spielerobjekt undfalse , dass die Kollisionsreaktion erneut startet.

Wackidev
quelle
Aber das würde bedeuten, dass sie auch mit nichts anderem kollidieren.
Paul Manta
Ich werde noch etwas recherchieren. Das einzige, woran ich denken kann, ist: Vielleicht können Sie die Kollision ignorieren, indem Sie von OnCollisionEnter false zurückgeben?
Wackidev
@ Wackidev Dies ist nicht der Fall.
Rhys van der Waerden
@Paul Ich habe meine Antwort bearbeitet.
Wackidev
0

Ich vermute, Sie können die Namen der Objekte überprüfen oder den Objektklassen einen Namenswert hinzufügen und dann überprüfen, ob?

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");                
        }
    }
}

Dann haben Sie einfach eine andere Variable, mit der Sie nach Boosting suchen und diese zu den Prüfungen hinzufügen können.

BEARBEITEN: Diese Variable wurde hinzugefügt.

Lewis
quelle
Er weiß, wie man über Kollisionen informiert wird; Er möchte einfach nicht, dass etwas unternommen wird. In bestimmten Fällen möchte er die integrierte Kollisionsreaktion deaktivieren.
Wackidev
Was auch immer passiert, wenn die Kollision ausgelöst wird, geht doch zwischen die Klammern? Ich habe noch nie Unity verwendet, daher weiß ich es nicht, aber in cocos2d und XNA ist es so.
Lewis
Tatsächlich behandelt Unity die Kollisionen selbst über PhysX. OnCollisionEnter ist nur eine Benachrichtigungsmethode. Es ist nicht für die eigentliche Kollisionsreaktion ausgelegt.
Wackidev
0

Ich nehme an, Sie verwenden die Physik-Engine, um die 'Abweichung' automatisch basierend auf Form / Masse zu machen, wenn Dinge zusammenstoßen. Wenn dies der Fall ist, ändern Sie die Masse Ihrer Zombies auf einen sehr minimalen Wert und sie haben keinen Einfluss auf das Auto.

ADB
quelle
0

Hier gibt es zwei Klassen von Antworten:

  1. Ignorieren oder Deaktivieren von Kollisionen
    • Diese Lösungen werden das Problem nicht lösen, er möchte, dass die Zombies fliegen, wenn sie getroffen werden.
  2. Masse ändern:
    • Dies ist ein guter Ansatz. Vergessen Sie nicht, auch Inertia entsprechend zu ändern.
      • Sie können alternativ die Masse und die Trägheit des Autos beim Boosten ändern (wir tun dies, um die Auswirkungen aller nicht kinematischen Objekte auf ein Auto beim Boosten zu verringern).
      • Dies sollte sich nicht auf die Straße oder die Wände auswirken, sofern diese kinematisch sind.

Hoffe das hilft!

DwuLive
quelle
Zwei der vorhandenen Antworten aus dem Jahr vor sechs Jahren empfehlen bereits den hier vorgeschlagenen massenbasierten Ansatz. Gibt es eine neue Strategie, die Sie hinzufügen möchten?
DMGregory
Ich entschuldige mich, ich kann noch nicht upvoten und wollte sicherstellen, dass Paul Manta nicht in die Irre geführt wird.
DwuLive