Zum Beispiel bewegt sich der Spieler (in diesem Fall der Vogel oder die Kamera, welche auch immer Sie bevorzugen) vorwärts oder bewegt sich die ganze Welt rückwärts (der Vogel ändert nur die Y-Position und hat eine konstante X-Position)?
game-mechanics
platformer
Lendrit Ibrahimi
quelle
quelle
Antworten:
Ich bin nicht einverstanden mit etwas Philipp Antwort ; oder zumindest, wie er es präsentierte. Es gibt den Eindruck, dass es eine bessere Idee sein könnte, die Welt um den Spieler herum zu bewegen. wenn es das genaue Gegenteil ist. Also hier ist meine eigene Antwort ...
Beide Optionen können funktionieren, aber es ist im Allgemeinen eine schlechte Idee, die Physik umzukehren, indem man die Welt um den Spieler herum bewegt, anstatt den Spieler um die Welt.
Leistungsverlust / Verschwendung:
Die Welt wird normalerweise viele Objekte haben; Viele, wenn nicht die meisten, statisch oder schlafend. Der Spieler wird ein oder relativ wenige Objekte haben. Die ganze Welt um den Spieler zu bewegen, bedeutet, alles in der Szene außer dem Spieler zu bewegen. Statische Objekte, schlafende dynamische Objekte, aktive dynamische Objekte, Lichtquellen, Schallquellen usw .; alle müssen bewegt werden.
Das ist (offensichtlich) erheblich teurer als nur das zu bewegen, was sich tatsächlich bewegt (der Spieler und vielleicht noch ein paar Sachen).
Wartbarkeit & Erweiterbarkeit:
Wenn Sie die Welt um den Spieler bewegen, wird die Welt (und alles in ihr) der Punkt sein, an dem die Dinge am aktivsten geschehen. Jeder Fehler oder jede Änderung im System bedeutet, dass sich möglicherweise alles ändert. Dies ist kein guter Weg, um Dinge zu tun; Sie möchten, dass Bugs / Änderungen so isoliert wie möglich sind, damit Sie an keiner Stelle unerwartete Verhaltensweisen feststellen, an der Sie keine Änderungen vorgenommen haben.
Es gibt auch viele andere Probleme mit diesem Ansatz. Zum Beispiel werden viele Annahmen darüber gebrochen, wie die Dinge im Motor funktionieren sollen. Sie können dynamic beispielsweise nur
RigidBody
für den Player verwenden. Da sich ein Objekt mitRigidBody
nicht auf Kinematik eingestelltem Anhang beim Festlegen von Position / Drehung / Skalierung unerwartet verhält (was Sie für jedes Bild, für jedes Objekt in der Szene mit Ausnahme des Players tun würden 😨)Die Antwort ist also, den Spieler nur dann zu bewegen!
Nun ja und nein . Wie in Philipps Antwort erwähnt, würde in einem Spieltyp mit unbegrenzten Möglichkeiten (oder in jedem Spiel mit einem großen, nahtlosen Erkundungsbereich) eine zu große Entfernung vom Ursprung zu merklichen FPPEs ( Floating-Point Precision Errors ) führen. Überlaufe den numerischen Typ und verursache entweder einen Absturz deines Spiels oder lass die Spielewelt in Rauch aufgehen ... Auf Steroiden! 😵 (weil zu diesem Zeitpunkt FPPEs das Spiel bereits auf "normalen" Riss bringen würden)
Die eigentliche Lösung:
Tu weder noch beides! Sie sollten die Welt statisch halten und den Player darum herum bewegen. Aber "re-root" sowohl den Spieler als auch die Welt, wenn der Spieler anfängt, sich zu weit von der Wurzel (Position
[0, 0, 0]
) der Szene zu entfernen.Wenn Sie die relative Position der Dinge (Spieler zu der Welt um sie herum) beibehalten und diesen Vorgang in einem einzigen Frame-Update durchführen, wird der (tatsächliche) Spieler es nicht einmal bemerken!
Dazu haben Sie zwei Hauptoptionen:
Hier ist ein Beispiel für diesen Prozess in Aktion
Aber wie weit ist zu weit?
Wenn Sie sich den Quellcode von Unity ansehen, verwenden sie
1e-5
(0.00001
) als Grundlage für die Berücksichtigung von zwei Fließkommawerten, die innerhalb vonVector2
und "gleich" sindVector3
(die Datentypen, die für die Positionen, [Euler-] Rotationen und Skalierungen von Objekten verantwortlich sind). Da der Gleitkomma-Präzisionsverlust in beide Richtungen von Null entfernt auftritt, kann davon ausgegangen werden, dass alles, was unter1e+5
(100000
) von der Szenenwurzel / -ursprung entfernt ist, sicher funktioniert.Aber! Schon seit...
... dann ist es wahrscheinlich eine gute Idee, viel früher / öfter als die 100000-Einheiten-Marke neu zu wurzeln. Das Beispielvideo, das ich zur Verfügung gestellt habe, scheint dies zum Beispiel alle 1000 Einheiten zu tun.
quelle
Beide Optionen funktionieren.
Aber wenn Sie wollen, dass der Endlosläufer wirklich endlos ist, müssen Sie den Spieler stationär halten und die Welt bewegen. Andernfalls stoßen Sie möglicherweise an die Grenzen der Variablen, mit denen Sie die X-Position speichern. Eine Ganzzahl würde irgendwann überlaufen und eine Gleitkommavariable würde immer ungenauer werden, was das Gameplay nach einer Weile unangenehm machen würde. Sie können dieses Problem jedoch vermeiden, indem Sie einen Typ verwenden, der groß genug ist, damit niemand innerhalb der denkbaren Zeitspanne in einer Sitzung auf diese Probleme stößt (wenn ein Player 1000 Pixel pro Sekunde verschiebt, läuft nach 49 Tagen eine 32-Bit-Ganzzahl über).
Tun Sie also, was Ihnen konzeptionell intuitiver erscheint.
quelle
Aufbauend auf der Antwort von XenoRo könnte man anstelle der beschriebenen Methode zum erneuten Verwurzeln Folgendes tun:
Erstellen Sie einen kreisförmigen Puffer aus Teilen Ihrer generierten unendlichen Karte, durch den sich Ihr Charakter mit einer mit Modulo-Arithmetik aktualisierten Position bewegt (sodass Sie nur um den kreisförmigen Puffer herumlaufen). Ersetzen Sie Teile Ihres Puffers, sobald Ihr Charakter den Block verlässt. Die Spieler-Update-Gleichung würde ungefähr so lauten:
player.position = (player.position + player.velocity) % worldBuffer.width;
Hier ist ein Bildbeispiel von dem, wovon ich spreche:
Hier ist ein Beispiel dafür, was beim Umschließen am Ende passiert.
Mit dieser Methode laufen Sie nicht in Präzision Fehler immer, aber Sie können einen sehr großen Puffer machen brauchen , wenn Sie beabsichtigen , dies mit sehr weiten Blick Abstand in 3d zu tun (wie Sie noch in der Lage sein müssen sehen vor sich ). Wenn es ein flatterhafter Vogel ist, wird Ihr Block wahrscheinlich nur so groß sein, wie es sein muss, um eine einzelne Szene für einen einzelnen Bildschirm aufzunehmen, und Ihr Puffer kann sehr klein sein.
Beachten Sie, dass Sie mit ANY prng anfangen, sich wiederholende Ergebnisse zu erhalten, und die maximale Anzahl nicht wiederholender Sequenzen einer PRNG-Generation in der Regel geringer ist als die Länge von pow (2, Anzahl der intern verwendeten Bits), mit merzenne twister ist dies nicht der Fall Ein großes Problem, da 2,5 KB interner Status verwendet werden. Wenn Sie jedoch die winzige Variante verwenden, haben Sie 2 ^ 127-1 maximale Iterationen vor der Wiederholung (oder noch schlimmer). Dies ist jedoch immer noch eine astronomisch große Zahl . Sie können Probleme mit Wiederholungsperioden auch dann beheben, wenn Ihr PRNG über gute Lawinenmischfunktionen für die Saat (wenn Sie implizit mehr Status hinzufügen) wiederholt eine kurze Periode aufweist .
quelle
Wie bereits gefragt und akzeptiert, hängt es wirklich vom Umfang und Stil Ihres Spiels ab, aber da es nicht erwähnt wurde: FlappyBird bewegt das Hindernis über den Bildschirm und nicht den Spieler über die Welt.
Ein Spawner instanziiert Objekte außerhalb des Bildschirms mit einer festgelegten Geschwindigkeit in der
Vector2.left
Richtung.quelle