Ich habe mich gefragt, ob es einen möglichen Schaden gibt, wenn meine Spieleschleife so schnell läuft, wie es das System zulässt.
Ich habe derzeit eine Schleife, die durch Messen der verstrichenen Zeit in Nanosekunden die Spielelogik und die Renderlogik problemlos mit vordefinierten Geschwindigkeiten ausführt. Tatsächlich wird jede Logik, die ich in der Schleife tue, auf eine bestimmte Anzahl von Aufrufen pro Sekunde getaktet.
Die Schleife selbst läuft jedoch ungefähr so schnell wie sie möchte, was auf meiner Maschine ungefähr 11,7 Millionen Schleifen pro Sekunde ergibt.
Schleife (einfacher Pseudocode):
while(!isGameOver){
if(canPollInputs){
pollInputs()
}
while(canStepLogic){
stepLogic()
}
if(canRender){
render()
}
}
Meine Frage ist im Grunde, ob diese einfache Schleife, wenn sie nicht mit kontrollierter Geschwindigkeit läuft, einem System Schaden zufügen kann.
Bearbeiten: Das bedeutet, dass meine Logik 30-mal pro Sekunde (30 tps) ausgeführt wird, mein Renderer mit 60 fps ausgeführt wird, ich 100-mal pro Sekunde Eingaben abrufe und es gibt auch eine Logik, mit der Logik oder Rendern länger als erwartet fertig werden kann . Die Schleife selbst wird jedoch nicht gedrosselt.
Bearbeiten: Wenn Sie Thread.sleep()
z. B. die Hauptschleife auf 250 Schleifen pro Sekunde drosseln, führt dies zu einer Reduzierung, aber die Schleifen laufen mit etwa 570 Schleifen pro Sekunde anstelle der gewünschten 250 (Code wird hinzugefügt, wenn ich mich auf meinem Desktop-Computer befinde.)
Edit: Los geht's, ein funktionierender Java-Gameloop, um die Dinge zu klären. Fühlen Sie sich auch frei, es zu benutzen, aber fordern Sie es nicht von Ihnen an;)
private void gameLoop() {
// Time that must elapse before a new run
double timePerPoll = 1000000000l / targetPPS;
double timePerTick = 1000000000l / targetTPS;
double timePerFrame = 1000000000l / targetFPS;
int maxFrameSkip = (int) ( (1000000000l / MINIMUM_FPS) / timePerTick);
int achievedPPS = 0;
int achievedFPS = 0;
int achievedTPS = 0;
long timer = TimeUtils.getMillis();
int loops = 0;
int achievedLoops = 0;
long currTime = 0l;
long loopTime = 0l;
long accumulatorPPS = 0l;
long accumulatorTPS = 0l;
long accumulatorFPS = 0l;
long lastTime = TimeUtils.getNano();
while(!isRequestedToStop) {
currTime = TimeUtils.getNano();
loopTime = currTime - lastTime;
lastTime = currTime;
loops = 0;
accumulatorPPS += loopTime;
accumulatorTPS += loopTime;
accumulatorFPS += loopTime;
if(accumulatorPPS >= timePerPoll) {
pollInputs();
playerLogic();
achievedPPS++;
accumulatorPPS -= timePerPoll;
}
while(accumulatorTPS >= timePerTick && loops < maxFrameSkip) {
tick();
achievedTPS++;
accumulatorTPS -= timePerTick;
loops++;
}
// Max 1 render per loop so player movement stays fluent
if(accumulatorFPS >= timePerFrame) {
render();
achievedFPS++;
accumulatorFPS -= timePerFrame;
}
if(TimeUtils.getDeltaMillis(timer) > 1000) {
timer += 1000;
logger.debug(achievedTPS + " TPS, " + achievedFPS + " FPS, "
+ achievedPPS + " Polls, " + achievedLoops + " Loops");
achievedTPS = 0;
achievedFPS = 0;
achievedLoops = 0;
}
achievedLoops++;
}
}
Wie Sie sehen, wird fast kein Code in jeder Schleife ausgeführt, sondern immer eine bestimmte Auswahl, die davon abhängt, wie viel Echtzeit vergangen ist. Die Frage bezieht sich auf diese 'Worker-Schleife' und wie sie das System beeinflusst.
quelle
Antworten:
Dadurch läuft ein CPU-Kern immer zu 100%. Dies schadet dem System normalerweise nicht . CPUs sind so ausgelegt, dass sie stundenlang zu 100% laufen. Bei einem mobilen Gerät wird der Akku jedoch schnell entladen und das Gerät aufgeheizt, was Sie wahrscheinlich etwa einen Stern in Ihrer Filialbewertung kosten wird. Auf einem Desktop-Computer ist dies weniger problematisch, verbraucht jedoch mehr Strom. Dadurch dreht sich der CPU-Lüfter schneller, was zu Geräuschen und zur Verschwendung von CPU-Zyklen führen kann, die ansonsten von anderen Prozessen verwendet werden könnten. Obwohl dies keine kritischen Mängel sind, handelt es sich dennoch um einen schlechten Stil. Sie sollten sie daher nach Möglichkeit vermeiden.
Sie haben nichts darüber gesagt, wie Ihre Spiellogik-Schleife intern funktioniert, aber wenn Sie den Delta-Zeit-Ansatz verwenden (jede Berechnung, die Sie durchführen, nimmt die Zeit seit dem letzten Aufruf in Betracht), haben Sie es mit sehr kleinen Delta-Werten zu tun. Zeitwerte. Dies bedeutet, dass Sie auf Probleme mit Gleitkommaungenauigkeiten stoßen können, die alle Arten von seltsamen Verhaltensweisen verursachen können. Außerdem ist die Auflösung des Systemtimers häufig begrenzt. Wenn Ihre Logikschleife zu schnell ist, können Sie einen Delta-t-Wert von Null erhalten, der dann eine Division durch Null verursachen kann, was zu einem Absturz führt.
Um dieses Problem zu mindern, sollten Sie Ihre Bildrate (Grafik und Logik) auf das Maximum dessen beschränken, was das menschliche Auge wahrnehmen kann. Wie viel umstritten ist, hängt von der Art der Animation und der Art der angezeigten Anzeige ab. Die Schätzungen reichen jedoch von 40 FPS bis 120 FPS. Das bedeutet, dass Sie für jede Schleife eine minimale Ausführungszeit zwischen 20 ms und 8 ms festlegen müssen. Sollte eine Schleifeniteration schneller beendet werden, lassen Sie den CPU-Thread
sleep
für die verbleibende Zeitspanne.quelle
Sie verschwenden CPU-Zyklen. Das bedeutet geringere Akkulaufzeit bei Notebooks, Tablets und Handys, höhere Stromrechnungen, mehr Wärme, die von der Maschine erzeugt wird, lautere Lüfter. Außerdem kann es sein, dass Sie Zyklen von anderen wichtigen Systemprozessen essen (z. B. kann der Windows-Server ruckeln), was sich dann auf das Gameplay auswirken kann. Einige System-Scheduler in den heutigen vorbeugenden Multitasking-Systemen bestrafen auch Anwendungen, die zu viele Zyklen benötigen. Daher sind Sie möglicherweise zuerst schnell und können plötzlich seltsame Ruckler feststellen, wenn Sie vom System gedrosselt werden.
Viele Hardcore-Gamer bauen auch benutzerdefinierte PCs von Grund auf neu, die den Spezifikationen ihrer Fans entsprechen. In diesem Fall kann ein heißer Tag und die Hitze, die Ihr Spiel erzeugt, dazu führen, dass die Sicherheit in der Maschine ausgelöst wird (bestenfalls) oder dass Teile überhitzt und beschädigt werden sterben (im schlimmsten Fall). Wenn es sich also um Ihre Zielgruppe handelt, möchten Sie vielleicht sicherstellen, dass Sie immer ein wenig Platz "oben" lassen.
Schließlich gibt es Spielprobleme, bei denen Sie möglicherweise Spieler mit schnelleren Maschinen gegenüber denen mit langsameren bevorzugen. Wenn die Spielschleife auf eine bestimmte Frequenz begrenzt ist und zusätzliche Zyklen nur für nicht spielrelevante Aspekte (wie das Rendern von Grafiken mit höherer Wiedergabetreue, Surround-Sound-Effekten oder was auch immer) verwendet werden, wird Ihr Spiel fairer.
quelle
Du solltest keine nervösen Bewegungen / Spielabläufe haben
Es gibt zwei Möglichkeiten, wie Sie die Spiellogik implementieren können - in Echtzeit oder in Abhängigkeit von der Anzahl der "Runden" / Verarbeitungsschritte. Wenn sich ein Element in Ihrem Spiel nach links bewegt, ist die Bewegung dann anders, wenn Ihre stepLogic () 100 statt 50-mal aufgerufen wurde?
Wenn Ihr Code die verstrichene Zeit überall explizit behandelt und korrekt ausführt, ist dies möglicherweise in Ordnung. Wenn Ihr Code jedoch etwas enthält, das von der Anzahl der Schritte abhängt, treten unerwünschte Nebenwirkungen auf.
Erstens variiert die Geschwindigkeit von Dingen, die sich ständig bewegen sollten, unvorhersehbar (abhängig von der Prozessorauslastung), und dies führt zu sehr ärgerlichen Kontrollen - Sie können keinen präzisen Schlag oder Sprung ausführen, wenn das Spiel plötzlich schneller oder langsamer wird. Selbst bei Spielen ohne "Zucken" sieht es nervig und nervös aus, wenn sich die Dinge nicht reibungslos bewegen.
Zweitens kann es je nach Computergeschwindigkeit zu Problemen mit den Charakterfähigkeiten kommen - ein klassisches Beispiel ist das alte Quake-Problem, bei dem die maximale Sprungreichweite unbeabsichtigt von Ihren FPS abhing.
Diese Probleme können auch dann auftreten, wenn Sie versuchen, den Code fps-unabhängig zu machen. Die Anhäufung von Rundungsfehlern kann häufig zu solchen Fehlern führen.
quelle
Der einzige potenzielle Schaden ist der Stromverbrauch. Tun Sie dies also nicht auf Mobilgeräten. Umgekehrt verbringen viele eingebettete Systeme ihr ganzes Leben in einer Schleife und warten darauf, dass etwas passiert.
Früher war es ganz normal, Game-Frames einfach so schnell wie möglich zu rendern, manchmal sogar ohne Timer, um das Gameplay für unterschiedliche CPU-Geschwindigkeiten auszugleichen. Das Rennspiel von Bullfrog, Hi-Octane, war ein besonders schlimmes Opfer, und ich vermute, das ist es, worauf sich das Plakat mit Civ2 bezieht.
Ich empfehle Ihnen, die Eingaben bei jedem Durchlauf mindestens abzufragen, wenn Sie sich auf einem Windows-System oder einem ähnlichen System befinden, um eine schnelle Eingabeantwort zu gewährleisten.
quelle
swap
/present
/flip
-Funktion zu verwenden, um die Spielschleife zu regulieren.