Unlimited WordPress themes, graphics, videos & courses! Unlimited asset downloads! From $16.50/m
Advertisement
  1. Game Development
  2. Game Physics

Grundlegende 2D-Platformer-Physik, Teil 6: Objekt-Kollisionsreaktion

by
Difficulty:BeginnerLength:LongLanguages:
This post is part of a series called Basic 2D Platformer Physics .
Basic 2D Platformer Physics, Part 5: Object vs. Object Collision Detection
Basic 2D Platformer Physics, Part 7: Slopes Groundwork

German (Deutsch) translation by Valentina (you can also view the original English article)

In der vorherigen Folge der Serie haben wir einen Kollisionserkennungsmechanismus zwischen den Spielobjekten implementiert. In diesem Teil verwenden wir den Kollisionserkennungsmechanismus, um eine einfache, aber robuste physische Antwort zwischen den Objekten zu erstellen.

Die Demo zeigt das Endergebnis dieses Tutorials. Verwenden Sie WASD, um den Charakter zu bewegen. Die mittlere Maustaste erzeugt eine Einwegplattform, die rechte Maustaste erzeugt eine feste Kachel und die Leertaste erzeugt einen Charakterklon. Die Schieberegler ändern die Größe des Charakters des Spielers.

Die Demo wurde unter Unity 5.4.0f3 veröffentlicht, und der Quellcode ist auch mit dieser Version von Unity kompatibel.

Kollisionsreaktion

Nachdem wir alle Kollisionsdaten aus der Arbeit im vorherigen Teil haben, können wir eine einfache Antwort auf kollidierende Objekte hinzufügen. Unser Ziel hier ist es, den Objekten zu ermöglichen, sich nicht wie auf einer anderen Ebene zu durchlaufen - wir möchten, dass sie fest sind und als Hindernis oder Plattform für andere Objekte fungieren. Dazu müssen wir nur eines tun: das Objekt aus einer Überlappung herausbewegen, falls eine auftritt.

Decken Sie die zusätzlichen Daten ab

Wir benötigen einige zusätzliche Daten für die MovingObject-Klasse, um die Objekt-/Objektantwort zu verarbeiten. Zuallererst ist es schön, einen Booleschen Wert zu haben, um ein Objekt als kinematisch zu markieren - das heißt, dieses Objekt wird von keinem anderen Objekt herumgeschoben.

Diese Objekte eignen sich gut als Plattformen und können auch Plattformen bewegen. Sie sollen die schwersten Dinge sein, daher wird ihre Position in keiner Weise korrigiert - andere Objekte müssen sich entfernen, um Platz für sie zu schaffen.

Die anderen Daten, die ich gerne habe, sind Informationen darüber, ob wir auf einem Objekt oder auf dessen linker oder rechter Seite stehen usw. Bisher konnten wir nur mit Kacheln interagieren, aber jetzt können wir auch mit anderen Objekten interagieren.

Um dies in Einklang zu bringen, benötigen wir einen neuen Satz von Variablen, die beschreiben, ob der Charakter etwas nach links, rechts, oben oder unten drückt.

Das sind viele Variablen. In einer Produktionsumgebung würde es sich lohnen, diese in Flags umzuwandeln und statt all dieser Booleschen Werte nur eine ganze Zahl zu haben, aber der Einfachheit halber werden wir diese so lassen, wie sie sind.

Wie Sie vielleicht bemerken, haben wir hier ziemlich feinkörnige Daten. Wir wissen, ob der Charakter ein Hindernis im Allgemeinen in eine bestimmte Richtung schiebt oder schiebt, aber wir können auch leicht nachfragen, ob wir uns neben einem Plättchen oder einem Objekt befinden.

Überlappung verschieben

Erstellen wir die UpdatePhysicsResponse-Funktion, in der die Objekt-/Objektantwort behandelt wird.

Wenn das Objekt als kinematisch markiert ist, kehren wir einfach zurück. Wir behandeln die Antwort nicht, da das kinematische Objekt auf kein anderes Objekt reagieren muss - die anderen Objekte müssen darauf reagieren.

Das setzt voraus, dass wir kein kinematisches Objekt benötigen, um die richtigen Daten darüber zu haben, ob es ein Objekt auf die linke Seite schiebt usw. Wenn dies nicht der Fall ist, müsste dies ein wenig geändert werden, was ich Ich werde später auf der ganzen Linie berühren.

Beginnen wir nun mit den Variablen, die wir kürzlich deklariert haben.

Wir speichern die Ergebnisse des vorherigen Frames in den entsprechenden Variablen und gehen vorerst davon aus, dass wir kein anderes Objekt berühren.

Beginnen wir jetzt damit, alle unsere Kollisionsdaten zu durchlaufen.

Lassen Sie uns zunächst die Fälle behandeln, in denen sich die Objekte kaum berühren und sich nicht wirklich überlappen. In diesem Fall wissen wir, dass wir nichts wirklich verschieben müssen, sondern nur die Variablen festlegen.

Wie bereits erwähnt, ist der Indikator dafür, dass sich die Objekte berühren, dass die Überlappung auf einer der Achsen gleich 0 ist. Beginnen wir mit der Überprüfung der x-Achse.

Wenn die Bedingung erfüllt ist, müssen wir sehen, ob sich das andere Objekt auf der linken oder rechten Seite unseres AABB befindet.

Wenn es sich rechts befindet, setzen Sie das mPushesRightObject auf true und stellen Sie die Geschwindigkeit so ein, dass sie nicht größer als 0 ist, da sich unser Objekt nicht mehr nach rechts bewegen kann, da der Pfad blockiert ist.

Gehen wir genauso mit der linken Seite um.

Schließlich wissen wir, dass wir hier nichts weiter tun müssen, also fahren wir mit der nächsten Schleifeniteration fort.

Behandeln wir die y-Achse genauso.

Das ist auch ein guter Ort, um die Variablen für einen kinematischen Körper festzulegen, wenn dies erforderlich ist. Es wäre uns egal, ob die Überlappung gleich Null ist oder nicht, da wir sowieso kein kinematisches Objekt bewegen werden. Wir müssten auch die Geschwindigkeitsanpassung überspringen, da wir ein kinematisches Objekt nicht stoppen möchten. Wir werden dies alles für die Demo überspringen, da wir die Hilfsvariablen nicht für kinematische Objekte verwenden werden.

Nachdem das behandelt wurde, können wir die Objekte behandeln, die sich ordnungsgemäß mit unserem AABB überlappt haben. Bevor wir das tun, möchte ich Ihnen den Ansatz erläutern, den ich in der Demo zur Kollisionsreaktion gewählt habe.

Erstens sollte das andere Objekt unbewegt bleiben, wenn sich das Objekt nicht bewegt und wir darauf stoßen. Wir behandeln es als einen kinematischen Körper. Ich habe mich für diesen Weg entschieden, weil ich der Meinung bin, dass er allgemeiner ist und das Push-Verhalten bei der benutzerdefinierten Aktualisierung eines bestimmten Objekts immer weiter unten behandelt werden kann.

When we bump into another object the other object should not move

Wenn sich beide Objekte während der Kollision bewegten, teilen wir die Überlappung zwischen ihnen basierend auf ihrer Geschwindigkeit auf. Je schneller sie unterwegs waren, desto größer wird der Überlappungswert des Überlappungswerts.

Der letzte Punkt ist, ähnlich wie beim Tilemap-Antwortansatz, wenn ein Objekt fällt und beim Herunterfahren ein anderes Objekt sogar um ein Pixel horizontal zerkratzt, rutscht das Objekt nicht ab und geht weiter nach unten, sondern steht auf diesem einen Pixel.

When we bump into another object the other object should not move even if its coming vertically

Ich denke, dies ist der formbarste Ansatz, und es sollte nicht sehr schwierig sein, ihn zu ändern, wenn Sie mit einer Antwort anders umgehen möchten.

Setzen wir die Implementierung fort, indem wir den absoluten Geschwindigkeitsvektor für beide Objekte während der Kollision berechnen. Wir benötigen auch die Summe der Geschwindigkeiten, damit wir wissen, wie viel Prozent der Überlappung unser Objekt verschoben werden soll.

Beachten Sie, dass wir anstelle der in den Kollisionsdaten gespeicherten Geschwindigkeit den Versatz zwischen der Position zum Zeitpunkt der Kollision und dem vorherigen Frame verwenden. Dies ist in diesem Fall nur genauer, da die Geschwindigkeit den Bewegungsvektor vor der physischen Korrektur darstellt. Die Positionen selbst werden korrigiert, wenn das Objekt beispielsweise eine feste Kachel getroffen hat. Wenn wir also einen korrigierten Geschwindigkeitsvektor erhalten möchten, sollten wir ihn wie folgt berechnen.

Beginnen wir nun mit der Berechnung des Geschwindigkeitsverhältnisses für unser Objekt. Wenn das andere Objekt kinematisch ist, setzen wir das Geschwindigkeitsverhältnis auf eins, um sicherzustellen, dass wir den gesamten Überlappungsvektor verschieben, wobei die Regel eingehalten wird, dass das kinematische Objekt nicht verschoben werden darf.

Beginnen wir nun mit einem merkwürdigen Fall, in dem sich beide Objekte überlappen, aber beide überhaupt keine Geschwindigkeit haben. Dies sollte eigentlich nicht passieren, aber wenn ein Objekt erzeugt wird, das ein anderes Objekt überlappt, möchten wir, dass sie sich auf natürliche Weise auseinander bewegen. In diesem Fall möchten wir, dass sich beide um 50% des Überlappungsvektors bewegen.

Ein anderer Fall ist, wenn die speedSum auf der x-Achse gleich Null ist. In diesem Fall berechnen wir das richtige Verhältnis für die y-Achse und legen fest, dass wir 50% der Überlappung für die x-Achse verschieben sollen.

In ähnlicher Weise behandeln wir den Fall, in dem die speedSum nur auf der y-Achse Null ist, und berechnen im letzten Fall beide Verhältnisse richtig.

Nachdem die Verhältnisse berechnet wurden, können wir sehen, wie viel wir benötigen, um unser Objekt zu versetzen.

Bevor wir uns entscheiden, ob wir das Objekt außerhlb der Kollision auf der x- oder der y-Achse bewegen sollen, berechnen wir die Richtung, aus der die Überlappung stattgefunden hat. Es gibt drei Möglichkeiten: Entweder sind wir horizontal, vertikal oder diagonal auf ein anderes Objekt gestoßen.

Im ersten Fall möchten wir uns auf der x-Achse aus der Überlappung herausbewegen, im zweiten Fall möchten wir uns aus der Überlappung auf der y-Achse herausbewegen, und im letzten Fall möchten wir uns aus der Überlappung herausbewegen Achse hatte die geringste Überlappung.

Looking at our paths coming from each direction

Denken Sie daran, dass sich die AABBs sowohl auf der x- als auch auf der y-Achse überlappen müssen, um sich mit einem anderen Objekt zu überlappen. Um zu überprüfen, ob wir horizontal auf ein Objekt gestoßen sind, werden wir sehen, ob der vorherige Frame das Objekt bereits auf der y-Achse überlappt hat. Wenn dies der Fall ist und wir uns auf der x-Achse nicht überlappt haben, muss die Überlappung aufgetreten sein, da sich die AABBs im aktuellen Frame auf der x-Achse zu überlappen begannen und wir daher davon ausgehen, dass wir horizontal auf ein anderes Objekt gestoßen sind .

Berechnen wir zunächst, ob wir uns mit dem anderen AABB im vorherigen Frame überlappt haben.

Stellen Sie nun die Bedingung für das horizontale Verlassen der Überlappung ein. Wie bereits erläutert, mussten wir uns auf der y-Achse überlappen und im vorherigen Frame nicht auf der x-Achse überlappen.

Wenn das nicht der Fall ist, bewegen wir uns auf der y-Achse aus der Überlappung heraus.

Wie oben erwähnt, müssen wir auch das Szenario des diagonalen Aufpralls auf das Objekt abdecken. Wir sind diagonal auf das Objekt gestoßen, wenn sich unsere AABBs im vorherigen Frame auf keiner der Achsen überlappten, da wir wissen, dass sie sich im aktuellen Frame auf beiden Achsen überlappen, sodass die Kollision auf beiden Achsen gleichzeitig aufgetreten sein muss.

Wir wollen uns jedoch bei einer diagonalen Erhebung nur dann aus der Überlappung auf der Achse herausbewegen, wenn die Überlappung auf der x-Achse kleiner ist als die Überlappung auf der y-Achse.

Das sind alle Fälle gelöst. Jetzt müssen wir das Objekt tatsächlich aus der Überlappung herausbewegen.

Wie Sie sehen, behandeln wir dies sehr ähnlich wie in dem Fall, in dem wir kaum einen anderen AABB berühren, aber zusätzlich bewegen wir unser Objekt um den berechneten Versatz.

Die vertikale Korrektur erfolgt auf die gleiche Weise.

Das ist fast alles; Es gibt nur noch eine Einschränkung. Stellen Sie sich das Szenario vor, in dem wir gleichzeitig auf zwei Objekten landen. Wir haben zwei nahezu identische Kollisionsdateninstanzen. Während wir alle Kollisionen durchlaufen, korrigieren wir die Position der Kollision mit dem ersten Objekt und bewegen uns ein wenig nach oben.

Dann behandeln wir die Kollision für das zweite Objekt. Die gespeicherte Überlappung zum Zeitpunkt der Kollision ist nicht mehr aktuell, da wir uns bereits von der ursprünglichen Position entfernt haben. Wenn wir die zweite Kollision genauso behandeln würden wie die erste, würden wir uns wieder ein wenig nach oben bewegen Dadurch wird unser Objekt doppelt so weit korrigiert, wie es sollte.

Vertically landing on a group of objects

Um dieses Problem zu beheben, verfolgen wir, wie stark wir das Objekt bereits korrigiert haben. Lassen Sie uns den Vektor offsetSum deklarieren, bevor wir alle Kollisionen durchlaufen.

Stellen wir nun sicher, dass alle Offsets, die wir in diesem Vektor auf unser Objekt angewendet haben, addiert werden.

Und schließlich versetzen wir die Überlappung jeder aufeinanderfolgenden Kollision um den kumulativen Vektor der Korrekturen, die wir bisher durchgeführt haben.

Wenn wir nun gleichzeitig auf zwei Objekten gleicher Höhe landen, wird die erste Kollision ordnungsgemäß verarbeitet und die Überlappung der zweiten Kollision wird auf Null gesetzt, wodurch unser Objekt nicht mehr bewegt wird.

Vertically landing on a group of objects

Nachdem unsere Funktion fertig ist, stellen wir sicher, dass wir sie verwenden. Ein guter Ort, um diese Funktion aufzurufen, wäre nach dem CheckCollisions-Aufruf. Dazu müssen wir unsere UpdatePhysics-Funktion in zwei Teile aufteilen. Erstellen wir also jetzt den zweiten Teil in der MovingObject-Klasse.

Im zweiten Teil rufen wir unsere frisch fertiggestellte UpdatePhysicsResponse-Funktion auf und aktualisieren die allgemeinen Pushs-Variablen left, right, bottom und top. Danach müssen wir nur noch die Position anwenden.

Rufen wir nun in der Hauptspiel-Update-Schleife den zweiten Teil des Physik-Updates nach dem CheckCollisions-Aufruf auf.

Erledigt! Jetzt können sich unsere Objekte nicht mehr überlappen. Natürlich müssten wir in einer Spielumgebung einige Dinge wie Kollisionsgruppen usw. hinzufügen, sodass es nicht zwingend erforderlich ist, Kollisionen mit jedem Objekt zu erkennen oder darauf zu reagieren, aber dies sind Dinge, die davon abhängen, wie Sie möchten Haben Sie Dinge in Ihrem Spiel eingerichtet, damit wir uns nicht damit befassen.

Zusammenfassung

Das war's für einen weiteren Teil der einfachen 2D-Platformer-Physik-Reihe. Wir haben den im vorherigen Teil implementierten Kollisionserkennungsmechanismus verwendet, um eine einfache physikalische Reaktion zwischen Objekten zu erstellen.

Mit diesen Werkzeugen können Standardobjekte wie bewegliche Plattformen, Schubblöcke, benutzerdefinierte Hindernisse und viele andere Arten von Objekten erstellt werden, die nicht wirklich Teil der Tilemap sein können, aber dennoch in irgendeiner Weise Teil des ebenen Geländes sein müssen. Es gibt noch eine weitere beliebte Funktion, die unserer Physik-Implementierung noch fehlt, und das sind die Steigungen.

Hoffentlich werden wir im nächsten Teil damit beginnen, unsere Tilemap mit der Unterstützung für diese zu erweitern. Dies würde die grundlegenden Funktionen vervollständigen, die eine einfache physikalische Implementierung für einen 2D-Plattformer haben sollte, und das würde die Serie beenden.

Natürlich gibt es immer Raum für Verbesserungen. Wenn Sie also eine Frage oder einen Tipp haben, wie Sie etwas besser machen können, oder nur eine Meinung zum Tutorial haben, können Sie mich gerne im Kommentarbereich informieren!

Advertisement
Advertisement
Advertisement
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.