Wann sollte ich einen festen oder variablen Zeitschritt verwenden?

256

Sollte eine Spieleschleife auf festen oder variablen Zeitschritten basieren? Ist man immer überlegen oder variiert die richtige Wahl je nach Spiel?

Variabler Zeitschritt

Physik-Aktualisierungen werden als Argument "Seit der letzten Aktualisierung verstrichene Zeit" übergeben und sind daher von der Framerate abhängig. Dies kann bedeuten, Berechnungen durchzuführen als position += distancePerSecond * timeElapsed.

Vorteile : glatt, einfacher zu codieren
Nachteile : nicht deterministisch, bei sehr kleinen oder großen Schritten unvorhersehbar

deWiTTERS Beispiel:

while( game_is_running ) {
    prev_frame_tick = curr_frame_tick;
    curr_frame_tick = GetTickCount();
    update( curr_frame_tick - prev_frame_tick );
    render();
}

Fester Zeitschritt

Aktualisierungen akzeptieren möglicherweise nicht einmal eine "verstrichene Zeit", da davon ausgegangen wird, dass jede Aktualisierung für einen festgelegten Zeitraum durchgeführt wird. Berechnungen können wie folgt durchgeführt werden position += distancePerUpdate. Das Beispiel enthält eine Interpolation während des Renderns.

Vorteile : vorhersehbar, deterministisch (einfacher zu vernetzen, zu synchronisieren?), Klarerer Berechnungscode
Nachteile : nicht synchronisiert, um die V-Synchronisation zu überwachen (verursacht unruhige Grafiken, sofern Sie nicht interpolieren), begrenzte maximale Bildrate (sofern Sie nicht interpolieren) variable Zeitschritte annehmen (wie Pyglet oder Flixel )

deWiTTERS Beispiel:

while( game_is_running ) {
    while( GetTickCount() > next_game_tick ) {
        update();
        next_game_tick += SKIP_TICKS;
    }
    interpolation = float( GetTickCount() + SKIP_TICKS - next_game_tick )
                    / float( SKIP_TICKS );
    render( interpolation );
}

Einige Ressourcen

Nick Sonneveld
quelle
6
Verwenden Sie variable Zeitschritte für Ihr Spiel und feste Schritte für die Physik
Daniel Little
7
Ich würde nicht sagen, dass ein variabler Zeitschritt einfacher zu codieren ist, da Sie mit einem festen Zeitschritt "nicht alle Berechnungen mit einer zeitabhängigen Variablen überall verwechseln müssen". Nicht, dass es so schwer wäre, aber ich würde als Profi nicht "einfacher zu programmieren" hinzufügen.
pek
Es stimmt, ich denke, ich habe damit gemeint, dass Sie keine variablen Zeitschritte interpolieren müssten.
Nick Sonneveld
@pek da stimme ich dir zu Der variable Zeitschritt hat eine einfachere codierte Spielschleife, aber Sie müssen in Ihren Entitäten, die sich mit dieser Variabilität befassen, mehr codieren, um "Schritt zu machen". Ein festgelegter Zeitschritt ist komplizierter zu codieren (da Sie Zeitabweichungen genau ausgleichen und neu berechnen müssen, welche zusätzliche Verzögerung hinzugefügt werden muss oder wie viele Aktualisierungen übersprungen werden müssen, um ihn festzuhalten), hat jedoch eine einfachere Codierung für die Entitäten, die dies tun müssen immer mit dem gleichen zeitintervall umgehen. Im Großen und Ganzen ist keines der Ansätze eindeutig einfacher als das andere.
Shivan Dragon
Sie können diese visuall mit diesem Tool überprüfen: s3.amazonaws.com/picobots/assets/unity/jerky-motion/… obwohl es Ihnen keine Vorstellung davon gibt, wie sie aussehen würden, wenn die Bildrate variiert
Buddy

Antworten:

134

Es gibt zwei Probleme im Zusammenhang mit der Frage.

  • Sollte die physikalische Schrittfrequenz an die Bildfrequenz gebunden sein?
  • Sollte die Physik mit konstanten Deltas versehen werden?

In Glen Fielder's Fix your time step sagt er zu "Free the Physics". Das bedeutet, dass die Aktualisierungsrate Ihrer Physik nicht an Ihre Bildrate gebunden sein sollte .

Wenn die Bildwiederholrate beispielsweise 50 fps beträgt und die Simulation auf 100 fps ausgelegt ist, müssen wir bei jeder Aktualisierung der Anzeige zwei physikalische Schritte ausführen, um die Physik synchron zu halten.

In Erin Cattos Empfehlungen für Box2D befürwortet er dies ebenfalls.

Binden Sie den Zeitschritt also nicht an Ihre Framerate (es sei denn, Sie müssen wirklich, wirklich).

Sollte die Physik-Schrittfrequenz an Ihre Bildfrequenz gebunden sein? Nein.


Erins Gedanken zu Fixed Step vs. Variable Stepping:

Box2D verwendet einen Berechnungsalgorithmus, der als Integrator bezeichnet wird. Integratoren simulieren die physikalischen Gleichungen zu bestimmten Zeitpunkten. ... Wir mögen es auch nicht, wenn sich der Zeitschritt stark ändert. Ein variabler Zeitschritt erzeugt variable Ergebnisse, was das Debuggen erschwert.

Glen's Gedanken zu festen und variablen Schritten:

Korrigieren Sie Ihren Zeitschritt oder explodieren Sie

... Wenn Sie in einer Autosimulation eine Reihe sehr steifer Federbelastungen für Stoßdämpfer haben, können winzige Änderungen in dt die Simulation explodieren lassen. ...

Sollte die Physik mit konstanten Deltas versehen werden? Ja.


Der Weg, die Physik mit konstanten Deltas zu verbessern und die Aktualisierungsrate der Physik nicht an die Framerate zu binden, besteht darin, einen Zeitakkumulator zu verwenden. In meinem Spiel gehe ich noch einen Schritt weiter. Ich wende eine Glättungsfunktion auf die eingehende Zeit an. Auf diese Weise bewirken große FPS-Spikes, dass die Physik nicht zu weit springt, sondern dass sie für ein oder zwei Frames schneller simuliert werden.

Sie erwähnen, dass mit einer festen Rate die Physik nicht mit dem Display synchronisiert werden würde. Dies gilt, wenn die Zielphysikrate in der Nähe der Zielbildrate liegt. Es ist schlimmer, die Bildrate ist größer als die Physikrate. Im Allgemeinen ist es besser, eine Physik-Aktualisierungsrate zu erreichen, die doppelt so hoch ist wie die Ziel-FPS, wenn Sie es sich leisten können.

Wenn Sie sich keine hohe Aktualisierungsrate für die Physik leisten können, sollten Sie die Positionen der Grafiken zwischen den Frames interpolieren, damit die gezeichneten Grafiken sich reibungsloser bewegen, als sich die Physik tatsächlich bewegt.

deft_code
quelle
1
Ich habe The Floor is Jelly vor und nach dem Upgrade meiner Maschine gespielt und es war albern: Es war nicht dasselbe, weil die Physik in der Tat von der Spielschleife aufgerufen wurde (und so an die Bildrate gebunden war) und nicht von ein Timer. Mein altes Gerät war sehr schlecht, so dass es ständig zwischen Zeitlupe und Zeitraffer umschaltete und großen Einfluss auf das Gameplay hatte. Jetzt ist es nur noch eine sehr schnelle Bewegung. Wie auch immer, dieses Spiel ist ein gutes Beispiel dafür, wie problematisch dieses Problem werden kann (obwohl es immer noch ein süßes Spiel ist).
MasterMastic
55

Ich denke, es gibt wirklich 3 Optionen, aber Sie listen sie als nur 2 auf:

Option 1

Nichts tun. Versuchen Sie, in einem bestimmten Intervall zu aktualisieren und zu rendern, z. B. 60 Mal pro Sekunde. Wenn es zurückfällt, lass es und mach dir keine Sorgen. Die Spiele verlangsamen sich in ruckelige Zeitlupe, wenn die CPU nicht mit Ihrem Spiel Schritt halten kann. Diese Option funktioniert überhaupt nicht für Echtzeitspiele mit mehreren Benutzern, ist jedoch für Einzelspielerspiele geeignet und wurde in vielen Spielen erfolgreich verwendet.

Option 2

Verwenden Sie die Deltazeit zwischen den Aktualisierungen, um die Bewegung von Objekten zu variieren. In der Theorie großartig, besonders wenn nichts in Ihrem Spiel beschleunigt oder verlangsamt, sondern sich nur mit einer konstanten Geschwindigkeit bewegt. In der Praxis wird dies von vielen Entwicklern schlecht umgesetzt, was zu inkonsistenter Kollisionserkennung und -physik führen kann. Es scheint, dass einige Entwickler diese Methode für einfacher halten als sie ist. Wenn Sie diese Option nutzen möchten, müssen Sie Ihr Spiel erheblich verbessern und einige hochkarätige Berechnungen und Algorithmen herausbringen, z. B. mithilfe eines Verlet-Physik-Integrators (anstelle des Standard-Eulers, den die meisten Leute verwenden) und mithilfe von Strahlen zur Kollisionserkennung eher als einfache Pythagoras-Entfernungsprüfungen. Ich habe vor einiger Zeit bei Stack Overflow eine Frage dazu gestellt und einige großartige Antworten erhalten:

https://stackoverflow.com/questions/153507/calculate-the-position-of-an-accelerating-body-after-a-certain-time

Option 3

Verwenden Sie den Gaffer-Ansatz "Fix your time step". Aktualisieren Sie das Spiel in festen Schritten wie in Option 1, aber tun Sie dies mehrmals pro gerendertem Frame - je nachdem, wie viel Zeit vergangen ist -, damit die Spiellogik mit der Echtzeit Schritt hält und gleichzeitig in diskreten Schritten bleibt. Auf diese Weise funktionieren einfach zu implementierende Spielelogik wie Euler-Integratoren und einfache Kollisionserkennung immer noch. Sie haben auch die Möglichkeit, grafische Animationen basierend auf der Deltazeit zu interpolieren. Dies gilt jedoch nur für visuelle Effekte und hat keine Auswirkungen auf Ihre Kernlogik. Sie können möglicherweise in Schwierigkeiten geraten, wenn Ihre Aktualisierungen sehr intensiv sind. Wenn die Aktualisierungen zurückbleiben, benötigen Sie immer mehr davon, um auf dem Laufenden zu bleiben. Dadurch wird Ihr Spiel möglicherweise noch weniger reaktionsschnell.

Persönlich mag ich Option 1, wenn ich damit durchkomme, und Option 3, wenn ich mit Echtzeit synchronisieren muss. Ich respektiere, dass Option 2 eine gute Option sein kann, wenn Sie wissen, was Sie tun, aber ich kenne meine Grenzen gut genug, um mich davon fernzuhalten.

Iain
quelle
Zu Option 2: Ich bin mir nicht sicher, ob ein Raycast jemals schneller als Pythagoras-Entfernungsprüfungen sein kann, es sei denn, Sie wenden Pythagoras sehr brachial an, aber ein Raycast ist auch sehr teuer, wenn Sie keine Broadphase hinzufügen.
Kaj
4
Wenn Sie Verlet mit ungleichen Zeitschritten verwenden, werfen Sie das Baby mit dem Badewasser aus. Der Grund, warum Verlet so stabil ist wie es ist, ist, dass Fehler in nachfolgenden Zeitschritten aufgehoben werden. Wenn die Zeitschritte nicht gleich sind, passiert dies nicht und Sie befinden sich wieder im explodierenden Physikland.
drxzcl
Option 3 - Klingt nach Joel Martinez 'Beschreibung des XNA-Ansatzes.
topright
1
Das ist eine wirklich gute Antwort. Alle drei Optionen haben ihren Platz und es ist wichtig zu verstehen, wann sie angemessen sind.
Adam Naylor
Bei allen MMOs, an denen ich gearbeitet habe (EQ, Landmark / EQNext [cry], PS2 [kurz] und ESO), haben wir immer eine variable Frame-Zeit verwendet. Ich war noch nie an dieser Entscheidung beteiligt, bin nur nachträglich aufgetaucht und habe das genutzt, was andere beschlossen haben.
Mark Storer
25

Mir gefällt die Art und Weise, wie das XNA Framework feste Zeitschritte implementiert. Wenn ein bestimmter Draw-Aufruf etwas zu lange dauert, wird update so oft aufgerufen, bis er "aufholt". Shawn Hargreaves beschreibt es hier:
http://blogs.msdn.com/b/shawnhar/archive/2007/11/23/game-timing-in-xna-game-studio-2-0.aspx

In 2.0 hat sich das Verhalten beim Zeichnen geändert:

  • Rufen Sie Update so oft auf, bis Sie die aktuelle Uhrzeit erreicht haben
  • Rufen Sie Draw einmal an
  • Warten Sie, bis es Zeit für das nächste Update ist

Meiner Meinung nach haben Sie einen der größten Profis erwähnt, der all Ihre Spielcode-Berechnungen so viel einfacher macht, weil Sie diese Zeitvariable nicht überall einbeziehen müssen.

Hinweis: xna unterstützt auch variable Zeitschritte. Dies ist nur eine Einstellung.

Joel Martinez
quelle
Dies ist die gebräuchlichste Art, eine Spieleschleife zu erstellen. Bei der Arbeit mit Mobilgeräten ist die Akkulaufzeit jedoch nicht optimal.
Ritter666
1
@ knight666; Schlagen Sie vor, dass die reduzierte Anzahl von Iterationen bei Verwendung eines längeren Zeitschritts Batterielebensdauer spart?
Falstro
Das ist immer noch ein variables Update - das Update-Delta ändert sich basierend darauf, wie lange das Rendern des Frames gedauert hat, anstatt auf einen festen Wert (dh 1/30 Sekunde).
Dennis Munsie
1
@ Tennis: Wie ich es verstehe, wird die Update-Funktion mit einem festen Delta aufgerufen ...
RCIX
3
@ knight666 Äh - wie findest du das? Wenn Sie vsync aktiviert haben und nicht stottern, sollten diese Methoden identisch sein! Und wenn Sie vsync off Sie aktualisieren mehr als oft Sie müssen und wahrscheinlich verschwenden CPU (und damit Batterie) durch nicht lassen ihn im Leerlauf!
Andrew Russell
12

Es gibt noch eine andere Option - Spiele-Update und Physik-Update entkoppeln. Der Versuch, die Physik-Engine auf den Zeitschritt des Spiels abzustimmen, führt zu Problemen, wenn Sie Ihren Zeitschritt korrigieren (das Problem, dass die Integration außer Kontrolle gerät, weil mehr Zeitschritte erforderlich sind, die mehr Zeit benötigen, die mehr Zeitschritte erfordern), oder wenn Sie sie variabel machen und eine wackelige Physik erzielen.

Die Lösung, die ich oft sehe, besteht darin, die Physik in einem festen Zeitschritt in einem anderen Thread (auf einem anderen Kern) laufen zu lassen. Das Spiel interpoliert oder extrapoliert die beiden zuletzt gültigen Frames, die es erfassen kann. Interpolation fügt eine gewisse Verzögerung hinzu, Extrapolation fügt eine gewisse Unsicherheit hinzu, aber Ihre Physik wird stabil sein und Ihren Zeitschritt nicht außer Kontrolle bringen.

Dies ist nicht trivial zu implementieren, könnte sich aber als zukunftssicher erweisen.

Kaj
quelle
8

Persönlich verwende ich eine Variation von variablen Zeitschritten (was meiner Meinung nach eine Art Hybrid aus festen und variablen Schritten ist). Ich habe dieses Timing-System auf verschiedene Arten getestet und benutze es für viele Projekte. Empfehle ich es für alles? Wahrscheinlich nicht.

Meine Spielschleifen berechnen die Anzahl der zu aktualisierenden Frames (nennen wir dies F) und führen dann F diskrete Logikaktualisierungen durch. Jedes Logik-Update setzt eine konstante Zeiteinheit voraus (die in meinen Spielen oft eine Hundertstelsekunde beträgt). Jede Aktualisierung wird der Reihe nach durchgeführt, bis alle F Aktualisierungen der diskreten Logik durchgeführt wurden.

Warum diskrete Aktualisierungen in logischen Schritten? Nun, wenn Sie versuchen, kontinuierliche Schritte zu verwenden, und plötzlich Störungen in der Physik auftreten, werden die berechneten Geschwindigkeiten und zurückgelegten Strecken mit einem riesigen Wert von F multipliziert.

Eine schlechte Implementierung würde nur F = aktuelle Zeit - Aktualisierungen der letzten Frame-Zeit bewirken. Wenn die Berechnungen jedoch zu weit zurückliegen (manchmal aufgrund von Umständen, die außerhalb Ihrer Kontrolle liegen, wie z. B. ein anderer Prozess, der die CPU-Zeit stiehlt), werden Sie schnell ein schreckliches Überspringen feststellen. Schnell wird aus dem stabilen FPS, den Sie beibehalten möchten, ein SPF.

In meinem Spiel erlaube ich eine "sanfte" (Art) Verlangsamung, um das Ausmaß des logischen Nachholens zu begrenzen, das zwischen zwei Ziehungen möglich sein sollte. Ich mache dies durch Klemmen von: F = min (F, MAX_FRAME_DELTA), was normalerweise MAX_FRAME_DELTA = 2/100 * s oder 3/100 * s hat. Also, anstatt Frames zu überspringen, wenn sie zu weit hinter der Spielelogik liegen, verwerfen Sie jeden massiven Frame-Verlust (der die Dinge verlangsamt), stellen Sie ein paar Frames wieder her, zeichnen Sie und versuchen Sie es erneut.

Auf diese Weise stelle ich auch sicher, dass die Steuerelemente des Players näher an den tatsächlichen Anzeigen auf dem Bildschirm ausgerichtet sind.

Der Pseudocode des Endprodukts sieht ungefähr so ​​aus (Delta ist F, wie bereits erwähnt):

// Assume timers have 1/100 s resolution
const MAX_FRAME_DELTA = 2
// Calculate frame gap.
var delta = current time - last frame time
// Clamp.
delta = min(delta, MAX_FRAME_RATE)
// Update in discrete steps
for(i = 0; i < delta; i++)
{
    update single step()
}
// Caught up again, draw.
render()

Diese Art der Aktualisierung ist nicht für alles geeignet, aber für Spiele im Arcade-Stil würde ich es vorziehen, wenn das Spiel langsamer wird, da viel los ist, als Frames zu verpassen und die Kontrolle über den Spieler zu verlieren. Ich bevorzuge dies auch anderen zeitvariablen Schritten, bei denen irreproduzierbare Störungen durch Bildverlust auftreten.

Overkill
quelle
Stimme dem letzten Punkt nachdrücklich zu; In so gut wie allen Spielen sollte sich die Eingabe verlangsamen, wenn die Framerate sinkt. Auch wenn dies in einigen Spielen (z. B. im Mehrspielermodus) nicht möglich ist, wäre es dennoch besser, wenn dies möglich wäre. : P Es fühlt sich einfach besser an, als einen langen Rahmen zu haben und dann die Spielwelt in den richtigen Zustand zu „springen“.
Ipsquiggle
Ohne feste Hardware wie einen Arcade-Automaten verlangsamen Arcade-Spiele die Simulation, wenn die Hardware nicht mithalten kann und das Spielen auf einem langsameren Automaten das Betrügen erschwert.
Joe, das ist nur wichtig, wenn es uns um "Betrug" geht. In den meisten modernen Spielen geht es nicht wirklich um den Wettbewerb zwischen Spielern, sondern nur darum, eine unterhaltsame Erfahrung zu machen.
Iain
1
Iain, wir sprechen hier speziell über Arcade-Spiele, die traditionell auf Highscore-Listen / Bestenlisten basieren. Ich spiele eine Menge Shmups und ich weiß, wenn ich finde, dass jemand Punkte mit künstlicher Verlangsamung auf Bestenlisten veröffentlicht, möchte ich, dass ihre Punkte gelöscht werden.
Ich versuche nicht, Ihre Antwort zu verringern, aber ich würde dies als festen Schritt interpretieren, bei dem das Rendern nicht direkt an die Aktualisierungsrate der Physik gebunden ist, außer dass das Aufholen der Physik Vorrang vor dem Rendern hat. Es hat definitiv gute Eigenschaften.
AaronLS
6

Diese Lösung gilt nicht für alles, aber es gibt eine andere Ebene variabler Zeitschritte - variable Zeitschritte für jedes Objekt auf der Welt.

Dies scheint kompliziert zu sein, und es kann auch sein, aber denken Sie daran, dass Sie Ihr Spiel als diskrete Ereignissimulation modellieren. Jede Spielerbewegung kann als Ereignis dargestellt werden, das beginnt, wenn die Bewegung beginnt, und endet, wenn die Bewegung endet. Wenn es eine Interaktion gibt, bei der das Ereignis aufgeteilt werden muss (z. B. eine Kollision), wird das Ereignis abgebrochen und ein anderes Ereignis in die Ereigniswarteschlange verschoben (bei der es sich wahrscheinlich um eine Prioritätswarteschlange handelt, die nach Ereignisendzeit sortiert ist).

Das Rendern ist vollständig von der Ereigniswarteschlange getrennt. Die Anzeigemaschine interpoliert Punkte zwischen den Start- / Endzeiten des Ereignisses nach Bedarf und kann bei dieser Schätzung so genau oder so nachlässig sein, wie dies erforderlich ist.

Eine komplexe Implementierung dieses Modells finden Sie im Raumsimulator EXOFLIGHT . Es verwendet ein anderes Ausführungsmodell als die meisten Flugsimulatoren - ein ereignisbasiertes Modell anstelle des herkömmlichen festen Zeitscheibenmodells. Die grundlegende Hauptschleife dieser Art von Simulation sieht im Pseudocode folgendermaßen aus:

while (game_is_running)
{
   world.draw_to_screen(); 
   world.get_player_input(); 
   world.consume_events_until(current_time + time_step); 
   current_time += time_step; 
}

Der Hauptgrund für die Verwendung in einem Raumsimulator ist die Notwendigkeit, eine willkürliche Zeitbeschleunigung ohne Genauigkeitsverlust bereitzustellen. Einige Missionen in EXOFLIGHT können Jahre in Anspruch nehmen, und selbst eine 32-fache Beschleunigungsoption wäre unzureichend. Für eine verwendbare Sim ist eine Beschleunigung von über 1.000.000 erforderlich, was in einem Zeitscheibenmodell schwierig ist. Mit dem ereignisbasierten Modell erhalten wir beliebige Zeitraten von 1 s = 7 ms bis 1 s = 1 Jahr.

Das Ändern der Zeitrate ändert nicht das Verhalten der Sim, was ein kritisches Merkmal ist. Wenn nicht genügend CPU-Leistung zur Verfügung steht, um den Simulator mit der gewünschten Geschwindigkeit auszuführen, häufen sich die Ereignisse und wir können die Aktualisierung der Benutzeroberfläche einschränken, bis die Ereigniswarteschlange geleert ist. Ebenso können wir die Sim so schnell vorspulen, wie wir möchten, und sicherstellen, dass wir weder CPU verschwenden noch Genauigkeit einbüßen.

Fazit: Wir können ein Fahrzeug in einer langen, gemächlichen Umlaufbahn modellieren (mithilfe der Runge-Kutta-Integration) und ein anderes Fahrzeug, das gleichzeitig über den Boden hüpft - beide Fahrzeuge werden mit der entsprechenden Genauigkeit simuliert, da wir keinen globalen Zeitschritt haben.

Nachteile: Komplexität und Mangel an handelsüblichen Physik-Engines, die dieses Modell unterstützen :)

sehugg
quelle
5

Ein fester Zeitschritt ist nützlich, wenn die Gleitkommagenauigkeit berücksichtigt und Aktualisierungen konsistent gemacht werden sollen.

Da es sich um einen einfachen Code handelt, ist es hilfreich, ihn auszuprobieren und zu prüfen, ob er für Ihr Spiel funktioniert.

now = currentTime
frameTime = now - lastTimeStamp // time since last render()
while (frameTime > updateTime)
    update(timestep)
    frameTime -= updateTime     // update enough times to catch up
                                // possibly leaving a small remainder
                                // of time for the next frame

lastTimeStamp = now - frameTime // set last timestamp to now but
                                // subtract the remaining frame time
                                // to make sure the game will still
                                // catch up on those remaining few millseconds
render()

Das Hauptproblem bei der Verwendung eines festen Zeitschritts ist, dass Spieler mit einem schnellen Computer die Geschwindigkeit nicht nutzen können. Das Rendern mit 100 fps, wenn das Spiel nur mit 30 fps aktualisiert wird, entspricht dem Rendern mit 30 fps.

Abgesehen davon kann es möglich sein, mehr als einen festen Zeitschritt zu verwenden. Mit 60 fps können triviale Objekte (z. B. Benutzeroberfläche oder animierte Sprites) und mit 30 fps nicht-triviale Systeme (z. B. Physik und) aktualisiert werden. Hinter den Kulissen können auch langsamere Zeitgeber (z. B. Löschen nicht verwendeter Objekte, Ressourcen usw.) verwaltet werden.

Nick Bedford
quelle
2
Wenn das Spiel sorgfältig erstellt wurde, kann die Rendermethode eine Interpolation durchführen, um Aktualisierungen mit 30 fps durchzuführen, die nicht mit dem Rendern mit 30 fps identisch sind.
Ricket
3

Abgesehen von dem, was Sie bereits angegeben haben, kann es sein, dass Sie das Gefühl haben, Ihr Spiel zu haben. Wenn Sie nicht garantieren können, dass Sie immer eine konstante Bildrate haben, ist es wahrscheinlich, dass Sie irgendwo langsamer werden und feste und variable Zeitschritte sehr unterschiedlich aussehen. Behoben hat den Effekt, dass Ihr Spiel für eine Weile in Zeitlupe läuft, was manchmal der beabsichtigte Effekt sein kann. Variable Zeitschritte sorgen dafür, dass sich die Dinge in Bezug auf die Zeit mit der richtigen Geschwindigkeit bewegen. Es kann jedoch zu plötzlichen Positionsänderungen usw. kommen, die es dem Spieler erschweren können, Aktionen genau auszuführen.

Ich kann nicht wirklich erkennen, dass ein festgelegter Zeitschritt die Dinge in einem Netzwerk einfacher macht. Sie wären zunächst alle leicht nicht synchron und würden auf einer Maschine langsamer, aber keine andere würde die Dinge mehr aus der Synchronität bringen.

Ich habe mich immer persönlich für den variablen Ansatz interessiert, aber diese Artikel enthalten einige interessante Dinge, über die man nachdenken muss. Ich habe jedoch immer noch häufig feste Schritte gefunden, insbesondere auf Konsolen, bei denen die Framerate konstant 60 fps ist, verglichen mit den sehr hohen Raten, die auf dem PC erzielt werden können.

identitycrisisuk
quelle
5
Sie sollten auf jeden Fall den Link Gaffer on Games im Originalbeitrag lesen. Ich denke nicht, dass dies eine schlechte Antwort per se ist, also werde ich nicht darüber abstimmen, aber ich stimme keinem Ihrer Argumente zu .
Falstro
Ich denke nicht, dass eine Verlangsamung in einem Spiel aufgrund eines festen Zeitschritts jemals beabsichtigt sein kann, weil es an mangelnder Kontrolle liegt. Mangelnde Kontrolle ist per definitionem eine Übergabe an den Zufall und kann daher nicht beabsichtigt sein. Es kann sein, was Sie sich vorgestellt haben, aber so weit möchte ich noch gehen. Was feste Zeitschritte im Netzwerk angeht, gibt es ein klares Plus, da es ziemlich unmöglich ist, die Physik-Engines auf zwei verschiedenen Computern ohne denselben Zeitschritt synchron zu halten. Da die einzige Möglichkeit zum Synchronisieren darin besteht, alle Entitätstransformationen zu senden, wäre dies viel zu bandbreitenintensiv.
Kaj
0

Verwenden Sie den Gaffer-Ansatz "Fix your time step". Aktualisieren Sie das Spiel in festen Schritten wie in Option 1, aber tun Sie dies mehrmals pro gerendertem Frame - je nachdem, wie viel Zeit vergangen ist -, damit die Spiellogik mit der Echtzeit Schritt hält und gleichzeitig in diskreten Schritten bleibt. Auf diese Weise funktionieren einfach zu implementierende Spielelogik wie Euler-Integratoren und einfache Kollisionserkennung immer noch. Sie haben auch die Möglichkeit, grafische Animationen basierend auf der Deltazeit zu interpolieren. Dies gilt jedoch nur für visuelle Effekte und hat keine Auswirkungen auf Ihre Kernlogik. Sie können möglicherweise in Schwierigkeiten geraten, wenn Ihre Aktualisierungen sehr intensiv sind. Wenn die Aktualisierungen zurückbleiben, benötigen Sie immer mehr davon, um auf dem Laufenden zu bleiben. Dadurch wird Ihr Spiel möglicherweise noch weniger reaktionsschnell.

Persönlich mag ich Option 1, wenn ich damit durchkomme, und Option 3, wenn ich mit Echtzeit synchronisieren muss. Ich respektiere, dass Option 2 eine gute Option sein kann, wenn Sie wissen, was Sie tun, aber ich kenne meine Grenzen gut genug, um mich davon fernzuhalten


quelle
Wenn Sie Antworten stehlen wollen, schreiben Sie die Person wenigstens gut!
PrimRock
0

Ich habe festgestellt, dass feste Zeitschritte, die mit 60 fps synchronisiert sind, eine spiegelglatte Animation ergeben. Dies ist besonders wichtig für VR-Anwendungen. Alles andere ist körperlich übel.

Variable Zeitschritte sind für VR nicht geeignet. Schauen Sie sich einige Unity VR-Beispiele an, die variable Zeitschritte verwenden. Es ist unangenehm.

Die Regel ist, wenn Ihr 3D-Spiel im VR-Modus flüssig ist, wird es im Nicht-VR-Modus ausgezeichnet sein.

Vergleichen Sie diese beiden (Cardboard VR-Apps)

(Variable Zeitschritte)

(Feste Zeitschritte)

Ihr Spiel muss Multithreading-fähig sein, um eine konsistente Zeit- / Bildrate zu erzielen. Physik, Benutzeroberfläche und Rendering müssen in dedizierte Threads unterteilt werden. Es ist scheußlich, sie mit PITA zu synchronisieren, aber das Ergebnis ist genau das, was Sie möchten (insbesondere für VR).

Handyspiele sind insb. Eine Herausforderung, da die Leistung der eingebetteten CPUs und GPUs begrenzt ist. Verwenden Sie sparsam GLSL (Slang), um so viel Arbeit wie möglich von der CPU zu entladen. Beachten Sie, dass die Übergabe von Parametern an die GPU Busressourcen beansprucht.

Halten Sie Ihre Bildrate während der Entwicklung immer angezeigt. Das eigentliche Spiel ist, es auf 60 fps zu fixieren. Dies ist die native Synchronisationsrate für die meisten Bildschirme und auch für die meisten Augäpfel.

Das von Ihnen verwendete Framework sollte in der Lage sein, Sie über eine Synchronisierungsanforderung zu benachrichtigen oder einen Timer zu verwenden. Fügen Sie keine Schlaf- / Wartezeit ein, um dies zu erreichen - selbst geringfügige Abweichungen sind erkennbar.

Dominic Cerisano
quelle
0

Variable Zeitschritte sind für Prozeduren, die so oft wie möglich ausgeführt werden sollen: Rendern von Zyklen, Ereignisbehandlung, Netzwerkmaterial usw.

Feste Zeitschritte sind dafür vorgesehen, dass etwas vorhersehbar und stabil sein muss. Dies beinhaltet, ist aber nicht beschränkt auf Physik- und Kollisionserkennung.

In der Praxis sollten Physik und Kollisionserkennung in einem eigenen Zeitschritt von allem anderen entkoppelt werden. Der Grund für die Durchführung solcher Verfahren in einem kleinen festen Zeitschritt besteht darin, sie genau zu halten. Die Impulswerte hängen stark von der Zeit ab, und wenn das Intervall zu groß wird, wird die Simulation instabil, und verrücktes Zeug passiert wie ein Ball, der in Phasen durch den Boden springt oder aus der Spielwelt springt. Beides ist nicht wünschenswert.

Alles andere kann in einem variablen Zeitschritt ausgeführt werden (obwohl es professionell gesehen oft eine gute Idee ist, das Rendern auf einen festen Zeitschritt zu beschränken). Damit eine Game-Engine reagieren kann, sollten Dinge wie Netzwerknachrichten und Benutzereingaben so schnell wie möglich behandelt werden, was bedeutet, dass das Intervall zwischen den Abfragen idealerweise so kurz wie möglich sein sollte. Dies bedeutet im Allgemeinen variabel.

Alles andere kann asynchron gehandhabt werden, was das Timing zu einem Streitpunkt macht.

Ian Young
quelle