Du bist nicht angemeldet.

Werbeanzeige

1

14.11.2017, 17:53

Player Movement mit Collision-Detection & -Response im "3D Platformer"

Hallo Zusammen,

ich bin nun seit einiger Zeit dabei an einem 3D Platformer zu arbeiten... Zumindest glaube ich, dass man das so nennt. Im Prinzip geht es darum, dass der Spieler über fliegende Platformen - verbunden durch Brücken, Stangen u.ä. - laufen / springen kann und seinen Weg durch eine Art 3D Labyrinth finden muss.

Nun stört mich seit einiger Zeit schon die Art und Weise, wie meine Spielfigur sich durch das Level bewegt, der Ablauf ist momentan wie folgt:
Schritt 1 - Horizontale Bewegung:
  • Über Inputs Horizontale Geschwindigkeit (rechts, links, vor, zurück) bestimmen.
  • Collision-Detection mit einer Ellipse um den Spieler und den Triangles der Kollisionsobjekte.
  • Kommt es zu einer Kollision setzt der Spieler entlang einer Gleitebene seinen Weg fort, der Bewegungsvektor wird also "umgebogen". Dadurch sind mehrere Kollisionen in einem Frame möglich, bis eine Position ohne Kollision gefunden wurde oder die maximale Anzahl an eingestellten Kollisionen erreicht wurde (momentan max. 4 Kollisionen).
Schritt 2 - Vertikale Bewegung:
  • Vertikale Geschwindigkeit über Gravitation + Sprunggeschwindigkeit bestimmen
  • Collision-Detection & Response wie oben, allerdings mit max. 1 Kollision
In der Ebene funktioniert das alles super. Eine Ebene nach oben laufen ist auch kein Problem. Beim herab - und herunterlaufen ist das alles jedoch nicht sehr schön.
  • Auf einer schiefen Ebene zu Stehen bedeutet, dass der Spieler bei jeder noch so kleinen Steigung nach unten gleitet. Wenn ich vertikal jedoch kein Gleiten erlaube, dann bleibt der Spieler auch bei sehr starken Steigungen "am Hang" (z.B. 89,999°) stehen -> Möchte ich auch nicht, könnte ich jedoch vielleicht durch einen Abgleich mit einer Grenze der Steigung für Gleiten fixen.
  • Größeres Problem: Beim Herunterlaufen einer Ebene macht der Spieler kleine "Hoppelsprünge", ist also dazwischen immer in der Luft. Das möchte ich auch nicht, da ich z.B. die Möglichkeit zu Springen nur dann erlauben will, wenn der Spieler gerade am Boden ist.
Nun bin ich daran interessiert, wie das in anderen, vergleichbaren Spielen umgesetzt wird, hat da jemand eine Ahnung?.
Das einzige, das mir dazu einfällt ist, dass ich aus horizontaler und vertikaler Bewegung einen Bewegungsvektor mache, das führt allerdings dazu, dass der Spieler (a) kleiner Gräben vollkommen überläuft wenn nur einmal die vertikale Komponente hinzugefügt wird oder (b) stecken bleibt, wenn die vertikale Komponente nach jeder Kollision hinzugefügt wird.
Ich gehe mal davon aus, dass es da deutlich klügere und ausgefeiltere Ansätze geben muss, allerdings bin ich auf nichts dergleichen im lieben Google gestolpert, scheinbar lieben alle Leute Unity & Co, selber programmieren ist nicht mehr so in... :dash:

2

16.11.2017, 21:43

Ich bin jetzt kein Experte was 3D angeht, da ich aber ähnliches in 2D gemacht habe, und es mehr oder weniger die gleichen Probleme sind, gebe ich hier mal mein Senf dazu.

Auf einer schiefen Ebene zu Stehen bedeutet, dass der Spieler bei jeder noch so kleinen Steigung nach unten gleitet. Wenn ich vertikal jedoch kein Gleiten erlaube, dann bleibt der Spieler auch bei sehr starken Steigungen "am Hang" (z.B. 89,999°) stehen -> Möchte ich auch nicht, könnte ich jedoch vielleicht durch einen Abgleich mit einer Grenze der Steigung für Gleiten fixen.

Ich verstehe nicht so ganz, ob das heruntergleiten, obwohl man still steht, jetzt beabsichtigt ist oder nicht.
Falls nicht, solltest du herausfinden, warum man überhaupt anfängt herunterzugleiten, obwohl überhaupt keine Beschleunigung angewendet werden sollte.
Wenn der Spieler auf dem Boden steht, sollte keine Gravitation angewendet werden, und wenn keine Buttons gedrückt werden, sollte auch keine horizontale Geschwindigkeit da sein. Dementsprechend sollte einfach gar nichts passieren. Der an-Wänden-vorbei-gleit code sollte auch nur ausgeführt werden, wenn tatsächlich Geschwindigkeit da ist.
Eine Grenze zu ziehen, wie steil die Steigung sein darf, bevor man nicht mehr hochlaufen/stehen bleiben kann bzw. runterrutscht, ist auf jedenfall eine gute Idee. Das kann man ja einfach über die Normale herausfinden.


Größeres Problem: Beim Herunterlaufen einer Ebene macht der Spieler kleine "Hoppelsprünge", ist also dazwischen immer in der Luft. Das möchte ich auch nicht, da ich z.B. die Möglichkeit zu Springen nur dann erlauben will, wenn der Spieler gerade am Boden ist.

Die gängigste Art das zu lösen ist, denke ich, den Spieler einfach "runterzudrücken". Du schaust, ob er sich auf einer Schräge befindet, und dementsprechend drückst du ihn, beim herunterlaufen einfach ein paar Pixel nach unten.


Wenn du dich bei anderen Engines inspirieren möchtest, kann ich dem movement code von Quake empfehlen. Den findest du hier. Es braucht zwar eine Weile, bis man da durchsteigt, aber die Techniken, die da verwendet werden sind recht simpel und funktionieren gut.
Eine der wichtigsten Funktionen ist z.B. PM_FlyMove, die sich darum kümmert, Bewegungen auszuführen inklusive Kollisionsbehandlung.

In der Quake engine wird ein 3D Vektor für die Geschwindigkeit verwendet. Wenn eine Kollision auf dem Weg festgestellt wird, wird die Geschwindigkeit umgebogen, sodass die Geschwindigkeit entsprechend der Kollisionsfläche reduziert wird und danach daran entlang gleitet.
Dadurch bekommt ohne viel Arbeit ziemlich cooles movement und pseudo-physics.
Den Code dafür findest du übrigens in PM_ClipVelocity.

Das rauf/runter laufen von Treppen/Schrägen wird übrigens hier behandelt.

3

17.11.2017, 17:42

Vielen Dank für die ausführliche Antwort!

Der Spieler gleitet auf einer schrägen Ebene - unabhängig von der Steigung -, da ich eine konstante Gravitation auf ihn ausübe. Ein guter Einwand ist, keine Gravitation auf den Spieler auszuüben, wenn dieser den Boden berührt. Das habe ich gerade eingeführt -> Der Spieler gleitet natürlich nicht mehr ;)

Ich werde es mal versuchen die Bewegung an die Steigung der Ebene unter dem Spieler anzupassen. Ist nur ein wenig verzwickt, da man im 3D nicht nur hoch und runter läuft, sondern auch mal parallel zu einer Steigung... Also nicht das Bestimmen der Steigung, sondern was ich mit der Steigung an sich dann anfange.

Das mit dem Umbiegen des Geschwindigkeitsvektors habe ich so auch implementiert. Funktioniert auch problemlos und sieht gut aus. Nur die Schwerkraft macht mir zu schaffen.

Herzlichen Dank für den Code, ich werde ihn mir am Wochenende mal durchschauen!

Werbeanzeige