Was enthält der Interaktionscode, wenn zwei Objekte interagieren?


28

Denken Sie an eine Kugel und einen Feind oder an den Spieler und den Boden. Was enthält der Interaktionscode, wenn diese Objekte interagieren?


2
Auf welche Weise interagieren? Meinen Sie Kollisionserkennung? In diesem Fall würden Sie höchstwahrscheinlich sowohl eine Kollisionserkennungsklasse als auch einen Kollisionslösungs-Manager implementieren.
Captain Redmuff

Teilweise ja, ich interessiere mich sowohl für die Kollision als auch für das, was nach der Kollision passiert. Prüft die Kugel, ob sie sich in der Nähe des Feindes befindet oder umgekehrt? Und was passiert nach der Kollision? Kann ein Kugelobjekt einem feindlichen Objekt einfach mitteilen, dass es getroffen wurde? Wie Sie sehen, bin ich ziemlich verwirrt über die ganze Sache und es macht einige sehr schwer zu lesenden Code.
ThatOneGuy

Antworten:


23

TL; DR:

Ihre Spielobjekte kennen sich nicht aus und führen auch keine Prüfungen gegen andere Objekte durch. Sie erstellen ein Kollisionserkennungs- und -auflösungsmuster, das Ihre Spielobjekte überprüft und die entsprechenden Aktionen ausführt, um Ihre Spielphysik zu simulieren.

Das gute Zeug

Aus früheren Versuchen, die Kollisionserkennung zu schreiben und dieses Buch zu lesen , sind zwei Stufen für die Kollisionserkennung und die Kollisionsauflösung bekannt. Die erste Phase (Kollisionserkennung) ist ein Early-Out-Durchgang, in dem Sie feststellen, ob zwei Objekte möglicherweise kollidieren. Wenn zwei Objekte eine potenzielle Kollision bilden, übergeben Sie diese Objekte an die zweite Stufe (Kollisionsauflösung), um eine genauere Prüfung der Objekte durchzuführen und die Kollision zu beheben.

Irgendwo in Ihrer Engine / Ihrem Spiel werden Sie eine Reihe aller Objekte in Ihrer Welt halten. In jedem Frame würden Sie das Array durchlaufen und jedes Objekt mit einer einfachen Kollisionserkennung zwischen Begrenzungsrahmen und Kugel gegen jedes andere Objekt prüfen.

Pseudocode:

dectectCollisions(objects)
{
    for(objectA in objects)
    {
        for(objectB in objects)
        {
            if(objectA != objectB) //ignore self
            {
                if(BoundingSpheresIntersect(objectA, objectB))
                {
                    collisionResolver.addObjects(objectA, objectB);
                }
            }
        }
    }
}

Diese Art von Schleife ist recht ineffizient, lässt jedoch Raum für Verbesserungen durch räumliche Unterteilung, da Objekte, die garantiert zu weit voneinander entfernt sind, um kollidieren zu können.

Nachdem die beiden Objekte auf eine mögliche Kollision überprüft wurden (dh beide Objekte sind nahe genug, um zu kollidieren), werden die Objekte weitergeleitet, um eine genauere Kollisionserkennungsroutine durchzuführen.

Stellen Sie sich vor, Sie haben zwei Polygone mit zufälligen Formen und Größen, die nahe genug sind, um sich möglicherweise zu schneiden, aber aufgrund ihrer Geometrie nicht:

Bild über Google gefunden

Bei Verwendung von Begrenzungskugeln würden diese beiden Objekte ein falsches Positiv für eine mögliche Kollision erzeugen. Hier würden Sie dann einen genaueren Durchlauf durchführen, um festzustellen, ob sich die beiden Objekte tatsächlich schneiden.

Sobald Sie eine echte Kollision gefunden haben, führt Ihr Kollisionslösungsschritt die entsprechende Aktion aus, um die Objekte durch Anwenden von Kräften oder Momenten abhängig von der Granularität und den Anforderungen Ihrer Spielphysik aufzulösen.

In diesem Sinne können Sie den gesamten Prozess der Kollisionserkennung und -auflösung abstrahieren, sodass Ihre Objekte weder voneinander noch von dem Prozess, der zum Ermitteln und Lösen von Kollisionen erforderlich ist, etwas wissen müssen. Die beiden Klassen / Manager, die dies für Sie erledigen, müssen nur die grundlegenden Eigenschaften jedes Objekts kennen, um eine schnelle und fehlerhafte Prüfung auf Kollisionen durchzuführen, und dann eine gründlichere Prüfung, falls dies erforderlich sein sollte.


2
Insbesondere wäre das Mediator-Entwurfsmuster angemessen. Das Observer-Muster wäre eine gute Alternative, die eine ganz andere Absicht hat. Sie können eine ziemlich gute Zusammenfassung von ihnen in diesem Stackoverflow-Beitrag erhalten .
Kurtzbot

12

Eine Möglichkeit, wie Unreal Engine 3 damit umgeht:

Die Kugel erhält eine Kollisionsnachricht, die besagt, dass sie etwas getroffen hat, wobei ein Argument besagt, was sie getroffen hat. Es kann dann objectHit.takeDamage (self) aufrufen. Das Ziel erhält dann die TakeDamage-Nachricht mit einem Zeiger auf das Objekt, das es getroffen hat, und ergreift die entsprechende Aktion.

Ich persönlich mag diesen Ansatz, weil er bedeutet, dass die Kugel spezielle Aktionen ausführen kann (wie z. B. einen Explosionseffekt abhängig von der Art der getroffenen Gegenstände) und das Ziel je nach Art der Kugel spezielle Aktionen ausführen kann.

Es ist auch möglich, dass die Kugel weiß, was sie mit Zielen tut, und Funktionen wie objectHit.freeze (self) aufrufen kann. Dann weiß das Ziel, dass es von etwas getroffen wurde, das es einfriert, und was für ein Objekt das war.

BEARBEITEN: Diese Antwort ist als allgemeines Bild der Funktionsweise gedacht, da Sie wahrscheinlich nicht mit UE3 arbeiten. :)


10

Dieb hat dies in der Dark Engine mit Sources und Receptrons sehr gut gemacht. Ein Objekt kann beide Eigenschaften mit unterschiedlichen Typen haben. Zum Beispiel würde ein Wasserpfeil eine Quelle für WaterStim bei Kontakt haben. Eine Explosion hätte einen AoE FireStim.

Wenn ein Wasserpfeil auf ein Objekt trifft, durchsucht das Zielobjekt seine Receptrons nach Objekten, die nach einem WaterStim mit den entsprechenden Intensitätswerten suchen. Dann führt es den ihm zugeordneten Befehl aus (in diesem Fall wird eine brennende Fackel in eine ausgeschaltete Fackel verwandelt und eine Rauchwolke ausgestoßen).

Da in SystemShock2 dieselbe Engine verwendet wird, werden alle Schadensarten auf diese Weise behandelt. Verschiedene Kugeln haben unterschiedliche Stims und verschiedene Monster haben dann Receptrons für die verschiedenen Stim-Arten und verursachen Schaden in Höhe von 1 *, 2 *, 1 /. 2 Die Intensität hängt davon ab, ob der Munitionstyp "super effektiv" ist oder nicht.

Es schien ein sehr flexibles System zu sein, da Sie Objekte im Level-Editor mit Quellen und Empfängern versehen konnten (zum Beispiel, um eine einmalige Tür zu schaffen, die sich öffnet, wenn ein Brand ausbricht) message "wenn dem Objekt spezielle Skripte zugeordnet waren.

Was Sie nicht wollen, ist eine nXn-Interaktionsmatrix aller möglichen Objekte, die mit allen möglichen Objekten kollidieren, fest zu codieren! Indem Sie Interaktionen durch standardisierte Nachrichten verallgemeinern, vereinfachen Sie den Prozess.


Vom Standpunkt der Skripterstellung aus scheint dieser Ansatz der flexibelste und aussagekräftigste zu sein. Sehr cool.
Drhayes

-2

Eine Lösung besteht darin, die Container mit Kugeln und Spielern in getrennten Klassen zu halten und dann die main () -Funktion zu haben, die die Frame-Schleife für die Interaktion verantwortlich macht.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.