Ich hatte einige kleinere Frame-Drop-Probleme in einem 2D-XNA-Spiel.
Zunächst bin ich ein vsync'ed, gemischter Zeitschritt. Das ist:
IsFixedTimestep = false;
graphicsDeviceManager.SynchronizeWithVerticalRetrace = true;
Dies wird mit einem festen Physik-Zeitschritt von 120 Hz kombiniert, der mit dem in Fix Your Timestep! um nervöse Physikbewegungen zu vermeiden. Das Update wird also mit einem variablen Zeitschritt ausgeführt, und ein weiterer Tick wird mit einem festen Zeitschritt ausgeführt (die Idee stammt von Unitys Update / FixedUpdate).
Wenn sich ein Sprite mit gleichmäßiger Geschwindigkeit über den Bildschirm bewegt, fällt alle paar Sekunden ein Jitter / Schluckauf auf. Ein bisschen googeln hat mich vor einigen Jahren zu diesem Forumsbeitrag geführt, in dem ich über das gleiche Thema sprach.
Um dies zu testen, habe ich diesen Code einer Update-Methode hinzugefügt:
if(gameTime.ElapsedGameTime.TotalMilliseconds > 22)
{
Logger.Log(gameTime.ElapsedGameTime.TotalMilliseconds.ToString());
}
Sicher genug, alle paar Sekunden zeigte das Protokoll eine Zeit über 30 Millisekunden, normalerweise um 32. Da ein Frame mit 60 fps 16,6 Millisekunden entspricht, scheint ein Frame einfach verloren zu gehen. Ich habe zusätzlichen Code hinzugefügt, um den Bildschirm in diesem Fall rot zu blinken. Wiederum stelle ich sicher fest, dass die Kugel schluckt, wenn der Bildschirm rot blinkt. Wenn ein Frame einfach fallen gelassen wird, bedeutet dies, dass die Kugel stillsteht. Wenn der Frame schließlich ausgeführt wird, wird die Physik viermal ausgeführt (da sie doppelt so schnell wie der Monitor läuft, über zwei Frames) und die Kugel a bewegt Menge.
Jetzt bin ich mir nicht sicher, ob ich das beheben kann. Wenn dies tatsächlich eine Eigenart von XNA (und Gamedev im Allgemeinen?) Ist, kann der Frame-Drop unvermeidbar sein. Ich würde also entweder wissen, wie man den Frame-Drop entweder beseitigt oder wie sichtbar er ist. Noch ein paar Punkte:
1. Es ist wahrscheinlich nicht der GC.
In diesem Forumsbeitrag schienen sie das Problem bis zu einem Punkt zu verbessern, an dem der GC niemals / kaum laufen würde, und sahen das Problem immer noch. Um mich selbst zu überprüfen, habe ich einen Code hinzugefügt, der GC.GetTotalMemory(false)
jeden Frame überprüft. Wenn er aus dem letzten Frame entfernt wurde, protokollieren Sie "GC". Ich denke, ein Rückgang würde eine GC-Sammlung anzeigen, aber ich könnte mich irren. "GC" wurde unabhängig vom anderen Protokoll protokolliert, als ein Frame gelöscht wurde.
2. Ich kann keinen variablen Zeitschritt verwenden
Ich brauche die Physik, um über ein Netzwerk reproduzierbar zu sein. Dies bedeutet, dass es so deterministisch wie möglich sein muss (es spielt eigentlich keine 100% ige Rolle, aber es verursacht wahrnehmbare Artefakte, je weniger deterministisch es ist). Ich kann also nicht einfach die Geschwindigkeit von Objekten mit multiplizieren gameTime.ElapsedGameTime
.
3. Ich möchte IsFixedTimeStep nicht verwenden
Ich mag es, die Framerate ein bisschen unter meiner Kontrolle zu halten. Es gibt mehr Kontrolle über das Zeichnen und ermöglicht mehrere etwas unabhängige Frameraten. In dem Forumsbeitrag wurde auch angegeben, dass das Setzen von IsFixedTimeStep auf false das Problem behoben hat. Zugegeben, ich habe IsFixedTimeStep im Grunde selbst neu implementiert!
Außerdem IsFixedTimeStep = true;
hilft die Einstellung nicht beim Stottern.
4. Einige Ideen?
Wenn ich das Problem nicht beheben kann, kann ich es vielleicht irgendwie abmildern. Einige Ideen, die ich hatte, sind:
- Bewegungsunschärfe
- Geben Sie den Kugeln Spuren
- Erhöhen Sie das "Rauschen" auf dem Bildschirm, sodass ein Bildverlust ein kleines Problem darstellt
- Separates Update und Zeichnen in separate Threads?
- Mit Reißen und Unsynchronisieren von der vertikalen Rückverfolgung umgehen? Dies löst das Problem fast vollständig, aber die GPU-Nutzung geht zu 100%, da sie so schnell wie möglich aktualisiert und gezeichnet wird.
Vielleicht ist seit dem Forumsbeitrag 2008 auch etwas mit XNA passiert, das ich nutzen kann. Ansonsten bin ich mir nicht sicher, was ich gegen das Problem tun soll. Ist es ein wirklich kleines Problem? Ja! Ich würde aber gerne ein seidenweiches Spiel haben. Ich würde alle Ideen lieben!