Engine & platform

Korrektur von Time.deltaTime in Unity 2020.2 für flüssigeres Gameplay: Was hat es gebraucht?

TAUTVYDAS ŽILYS / UNITY TECHNOLOGIESContributor
Oct 1, 2020|18 Min.
Korrektur von Time.deltaTime in Unity 2020.2 für flüssigeres Gameplay: Was hat es gebraucht?
Diese Website wurde aus praktischen Gründen für Sie maschinell übersetzt. Die Richtigkeit und Zuverlässigkeit des übersetzten Inhalts kann von uns nicht gewährleistet werden. Sollten Sie Zweifel an der Richtigkeit des übersetzten Inhalts haben, schauen Sie sich bitte die offizielle englische Version der Website an.

Die Beta-Version von Unity 2020.2 behebt ein Problem, das auf vielen Entwicklungsplattformen auftritt: inkonsistente Time.deltaTime-Werte, die zu ruckelnden, stotternden Bewegungen führen. Lesen Sie diesen Blog-Beitrag, um zu verstehen, was los war und wie die neue Version von Unity Ihnen hilft, ein etwas flüssigeres Gameplay zu erstellen.

Seit den Anfängen der Spieleindustrie bedeutete das Erreichen einer framerate-unabhängigen Bewegung in Videospielen die Berücksichtigung der Frame-Delta-Zeit:

Unbekannter Blocktyp "codeBlock", bitte geben Sie einen Serializer dafür in der `serializers.types` prop an

Dadurch wird der gewünschte Effekt erzielt, dass sich ein Objekt mit konstanter Durchschnittsgeschwindigkeit bewegt, unabhängig von der Bildwiederholrate des Spiels. Theoretisch sollte sich das Objekt auch in einem gleichmäßigen Tempo bewegen, wenn die Bildrate stabil ist. In der Praxis ergibt sich ein ganz anderes Bild. Wenn Sie sich die tatsächlich gemeldeten Time.deltaTime-Werte angeschaut haben, haben Sie vielleicht folgendes gesehen:

Unbekannter Blocktyp "codeBlock", bitte geben Sie einen Serializer dafür in der `serializers.types` prop an

Dieses Problem betrifft viele Spiele-Engines, auch Unity, und wir sind unseren Benutzern dankbar, dass sie uns darauf aufmerksam gemacht haben. Erfreulicherweise beginnt Unity 2020.2 beta damit, dieses Problem zu lösen.

Wie kommt es dazu? Warum ist Time.deltaTime nicht jedes Mal gleich 1⁄144 Sekunden (~6,94 ms), wenn die Bildrate auf konstante 144 fps eingestellt ist? In diesem Blogbeitrag nehme ich Sie mit auf die Reise, um dieses Phänomen zu untersuchen und schließlich zu beheben.

Was ist die Deltazeit und warum ist sie wichtig?

Für den Laien ist die Deltazeit die Zeit, die Ihr letztes Bild gebraucht hat. Das klingt einfach, ist aber nicht so intuitiv, wie Sie vielleicht denken. In den meisten Büchern zur Spielentwicklung findet man diese kanonische Definition einer Spielschleife:

Unbekannter Blocktyp "codeBlock", bitte geben Sie einen Serializer dafür in der `serializers.types` prop an

Mit einer Spielschleife wie dieser ist es einfach, die Deltazeit zu berechnen:

Unbekannter Blocktyp "codeBlock", bitte geben Sie einen Serializer dafür in der `serializers.types` prop an

Dieses Modell ist zwar einfach und leicht zu verstehen, aber für moderne Spiel-Engines höchst unzureichend. Um eine hohe Leistung zu erzielen, verwenden Motoren heutzutage eine Technik namens "Pipelining", die es einem Motor ermöglicht, an mehr als einem Bild gleichzeitig zu arbeiten.

Vergleichen Sie dies:

Rahmen

Zu diesem:

Rahmen

In beiden Fällen benötigen die einzelnen Teile der Spielschleife die gleiche Zeit, aber im zweiten Fall werden sie parallel ausgeführt, so dass in der gleichen Zeit mehr als doppelt so viele Bilder ausgegeben werden können. Durch das Pipelining des Motors ändert sich die Rahmenzeit von der Summe aller Pipelinestufen zur längsten.

Aber auch das ist eine Vereinfachung dessen, was tatsächlich in jedem Bild in der Maschine passiert:

  • Jede Pipelinestufe benötigt für jedes Bild eine andere Zeitspanne. Vielleicht befinden sich in diesem Bild mehr Objekte auf dem Bildschirm als im letzten, so dass das Rendern länger dauert. Oder der Spieler hat mit dem Gesicht auf der Tastatur gerollt, so dass die Eingabe länger dauerte.
  • Da die verschiedenen Phasen der Pipeline unterschiedlich viel Zeit benötigen, müssen wir die schnelleren Phasen künstlich aufhalten, damit sie nicht zu weit vorankommen. In den meisten Fällen wird dies durch das Warten auf ein vorheriges Bild im vorderen Puffer (auch als Bildschirmpuffer bekannt) realisiert. Wenn VSync aktiviert ist, wird zusätzlich auf den Beginn der VBLANK-Periode des Displays synchronisiert. Darauf werde ich später noch näher eingehen.

Mit diesem Wissen im Hinterkopf, lassen Sie uns einen Blick auf eine typische Frame-Timeline in Unity 2020.1 werfen. Da die Auswahl der Plattform und verschiedene Einstellungen einen erheblichen Einfluss darauf haben, wird in diesem Artikel von einem Windows Standalone-Player mit aktiviertem Multithreading, deaktivierten Grafikjobs, aktiviertem Vsync und QualitySettings.maxQueuedFrames auf 2 ausgegangen, der auf einem 144-Hz-Monitor ohne Bildausfälle läuft. Klicken Sie auf das Bild, um es in voller Größe zu sehen:

Rahmen

Die Frame-Pipeline von Unity wurde nicht von Grund auf neu implementiert. Stattdessen hat sie sich im Laufe des letzten Jahrzehnts zu dem entwickelt, was sie heute ist. Wenn Sie auf frühere Versionen von Unity zurückblicken, werden Sie feststellen, dass sich diese alle paar Versionen ändern.

Vielleicht fallen Ihnen sofort ein paar Dinge auf:

  • Sobald die gesamte Arbeit an die GPU übertragen wurde, wartet Unity nicht darauf, dass dieses Bild auf den Bildschirm gespiegelt wird, sondern auf das vorherige. Dies wird durch die QualitySettings.maxQueuedFrames API gesteuert. Diese Einstellung beschreibt, wie weit der aktuell angezeigte Rahmen hinter dem aktuell gerenderten Rahmen liegen kann. Der kleinstmögliche Wert ist 1, da Sie bestenfalls framen+1 rendern können, wenn framen auf dem Bildschirm angezeigt wird. Da er in diesem Fall auf 2 gesetzt ist (was der Standard ist), stellt Unity sicher, dass Framen auf dem Bildschirm angezeigt wird, bevor es mit dem Rendern von Framen+2 beginnt (zum Beispiel wartet Unity, bevor es mit dem Rendern von Frame5 beginnt, dass Frame3 auf dem Bildschirm erscheint).
  • Das Rendern von Frame5 dauert auf der GPU länger als ein einzelnes Aktualisierungsintervall des Monitors (7,22 ms gegenüber 6,94 ms); allerdings wird keines der Frames fallengelassen. Dies geschieht, weil QualitySettings.maxQueuedFrames mit dem Wert 2 den Zeitpunkt verzögert, zu dem das eigentliche Bild auf dem Bildschirm erscheint, was einen Puffer in der Zeit erzeugt, der vor dem Fallenlassen von Bildern schützt, solange der "Spike" nicht zur Norm wird. Wäre er auf 1 gesetzt, hätte Unity den Rahmen sicher fallen lassen, da er das Werk nicht mehr überlappen würde.

Auch wenn die Bildschirmaktualisierung alle 6,94 ms erfolgt, zeigt das Zeitsample von Unity ein anderes Bild:

Mathematik

Der Mittelwert der Deltazeit in diesem Fall ((7,27 + 6,64 + 7,03)/3 = 6,98 ms) liegt sehr nahe an der tatsächlichen Bildwiederholfrequenz des Monitors (6,94 ms), und wenn Sie diesen Wert über einen längeren Zeitraum messen würden, würde er schließlich genau 6,94 ms betragen. Wenn Sie diese Deltazeit so verwenden, wie sie ist, um die Bewegung des sichtbaren Objekts zu berechnen, führen Sie leider einen sehr subtilen Jitter ein. Um dies zu veranschaulichen, habe ich ein einfaches Unity-Projekt erstellt. Es enthält drei grüne Quadrate, die sich durch den Weltraum bewegen:

Die Kamera ist am oberen Würfel befestigt, so dass er auf dem Bildschirm völlig ruhig erscheint. Wenn Time.deltaTime genau ist, scheinen auch der mittlere und der untere Würfel still zu stehen. Die Würfel bewegen sich jede Sekunde um die doppelte Breite des Bildschirms: Je höher die Geschwindigkeit, desto deutlicher wird das Zittern. Zur Veranschaulichung der Bewegung habe ich lila und rosa Würfel, die sich nicht bewegen, an festen Positionen im Hintergrund platziert, damit man erkennen kann, wie schnell sich die Würfel tatsächlich bewegen.

In Unity 2020.1 stimmen die mittleren und unteren Würfel nicht ganz mit der Bewegung des oberen Würfels überein - sie zittern leicht. Nachfolgend sehen Sie ein Video, das mit einer Zeitlupenkamera aufgenommen wurde (20-fache Verlangsamung):

Identifizierung der Quelle der Deltazeitschwankungen

Woher kommen also diese Unstimmigkeiten bei der Deltazeit? Das Display zeigt jedes Bild für eine feste Zeitspanne an, wobei das Bild alle 6,94 ms wechselt. Dies ist die tatsächliche Delta-Zeit, denn so lange dauert es, bis ein Bild auf dem Bildschirm erscheint, und so lange wird der Spieler jedes Bild beobachten.

Jedes Intervall von 6,94 ms besteht aus zwei Teilen: Verarbeitung und Ruhephase. Die Zeitleiste des Beispiels zeigt, dass die Deltazeit auf dem Haupt-Thread berechnet wird, daher werden wir uns darauf konzentrieren. Der Verarbeitungsteil des Hauptthreads besteht aus dem Pumpen von Betriebssystemmeldungen, der Verarbeitung von Eingaben, dem Aufruf von Update und der Ausgabe von Rendering-Befehlen. "Warten auf den Rendering-Thread" ist der schlafende Teil. Die Summe dieser beiden Intervalle ist gleich der tatsächlichen Rahmenzeit:

Mathematik

Diese beiden Zeitangaben schwanken aus verschiedenen Gründen bei jedem Bild, aber ihre Summe bleibt konstant. Erhöht sich die Bearbeitungszeit, verringert sich die Wartezeit und umgekehrt, so dass sie immer genau 6,94 ms betragen. Die Summe aller Teile, die zu der Wartezeit führen, beträgt immer 6,94 ms:

Mathematik

Unity fragt jedoch zu Beginn von Update die Zeit ab . Aus diesem Grund führt jede Abweichung in der Zeit, die für die Ausgabe von Rendering-Befehlen, die Ausgabe von Betriebssystemmeldungen oder die Verarbeitung von Eingabeereignissen benötigt wird, zu einer Verfälschung des Ergebnisses.

Eine vereinfachte Unity-Haupt-Thread-Schleife kann wie folgt definiert werden:

Unbekannter Blocktyp "codeBlock", bitte geben Sie einen Serializer dafür in der `serializers.types` prop an

Die Lösung für dieses Problem scheint einfach zu sein: Verschieben Sie die Zeitabtastung auf die Zeit nach der Wartezeit, so dass die Spielschleife wie folgt aussieht:

Unbekannter Blocktyp "codeBlock", bitte geben Sie einen Serializer dafür in der `serializers.types` prop an

Diese Änderung funktioniert jedoch nicht korrekt: Rendering hat andere Zeitwerte als Update(), was negative Auswirkungen auf alle möglichen Dinge hat. Eine Möglichkeit besteht darin, die abgetastete Zeit an diesem Punkt zu speichern und die Motorzeit erst zu Beginn des nächsten Frames zu aktualisieren. Das würde jedoch bedeuten, dass die Engine die Zeit vor dem Rendering des letzten Frames verwenden würde.

Da die Verschiebung von SampleTime() auf die Zeit nach Update() nicht effektiv ist, ist es vielleicht erfolgreicher, die Wartezeit an den Anfang des Frames zu verschieben:

Unbekannter Blocktyp "codeBlock", bitte geben Sie einen Serializer dafür in der `serializers.types` prop an

Leider führt dies zu einem weiteren Problem: Der Rendering-Thread muss nun das Rendering fast so schnell beenden, wie es angefordert wird, was bedeutet, dass der Rendering-Thread nur geringfügig von der parallelen Arbeit profitiert.

Werfen wir einen Blick zurück auf die Zeitachse des Rahmens:

Rahmen

Unity erzwingt die Pipeline-Synchronisation, indem es bei jedem Frame auf den Render-Thread wartet. Dies ist notwendig, damit der Hauptthread nicht zu weit vor dem läuft, was auf dem Bildschirm angezeigt wird. Der Render-Thread gilt als "fertig", wenn er das Rendering beendet hat und darauf wartet, dass ein Frame auf dem Bildschirm erscheint. Mit anderen Worten: Er wartet darauf, dass der hintere Puffer umgedreht und zum vorderen Puffer wird. Dem Render-Thread ist es jedoch egal, wann das vorherige Bild auf dem Bildschirm angezeigt wurde - nur der Haupt-Thread kümmert sich darum, weil er sich selbst drosseln muss. Anstatt den Render-Thread auf das Erscheinen des Bildes auf dem Bildschirm warten zu lassen, kann dieses Warten auf den Haupt-Thread verlagert werden. Nennen wir es WaitForLastPresentation(). Die Hauptschleife des Threads wird:

Unbekannter Blocktyp "codeBlock", bitte geben Sie einen Serializer dafür in der `serializers.types` prop an

Die Zeit wird nun direkt nach dem Warteteil der Schleife abgetastet, so dass das Timing mit der Aktualisierungsrate des Monitors übereinstimmt. Die Zeit wird auch am Anfang des Frames abgetastet, so dass Update() und Render() die gleichen Zeitangaben sehen.

Es ist sehr wichtig zu beachten, dass die Funktion WaitForLastPresention() nicht darauf wartet, dass das Bild 1 auf dem Bildschirm erscheint. Wenn das der Fall wäre, würde überhaupt kein Pipelining stattfinden. Stattdessen wird gewartet, bis framen - QualitySettings.maxQueuedFrames auf dem Bildschirm erscheint, so dass der Hauptthread fortfahren kann, ohne auf die Fertigstellung des letzten Frames zu warten (es sei denn, maxQueuedFrames ist auf 1 gesetzt, in diesem Fall muss jedes Frame fertiggestellt werden, bevor ein neues beginnt).

Erreichen von Stabilität: Wir müssen tiefer gehen!

Nach der Implementierung dieser Lösung wurde die Deltazeit viel stabiler als zuvor, aber es gab immer noch ein gewisses Zittern und gelegentliche Schwankungen. Wir sind darauf angewiesen, dass das Betriebssystem den Motor rechtzeitig aus dem Ruhezustand aufweckt. Dies kann mehrere Mikrosekunden dauern und daher die Deltazeit verfälschen, insbesondere auf Desktop-Plattformen, auf denen mehrere Programme gleichzeitig laufen.

Um das Timing zu verbessern, können Sie den genauen Zeitstempel eines Frames verwenden, der auf dem Bildschirm angezeigt wird (oder einen Puffer außerhalb des Bildschirms), den Sie mit den meisten Grafik-APIs/Plattformen extrahieren können. Direct3D 11 und 12 haben beispielsweise IDXGISwapChain::GetFrameStatistics, während macOS CVDisplayLink bietet. Dieser Ansatz hat jedoch auch einige Nachteile:

  • Sie müssen für jede unterstützte Grafik-API einen eigenen Extraktionscode schreiben, was bedeutet, dass der Zeitmessungscode jetzt plattformspezifisch ist und jede Plattform ihre eigene Implementierung hat. Da sich jede Plattform anders verhält, birgt eine solche Änderung die Gefahr katastrophaler Folgen.
  • Bei einigen Grafik-APIs muss VSync aktiviert sein, um diesen Zeitstempel zu erhalten. Das heißt, wenn VSync deaktiviert ist, muss die Zeit weiterhin manuell berechnet werden.

Ich glaube jedoch, dass dieser Ansatz das Risiko und die Mühe wert ist. Das mit dieser Methode gewonnene Ergebnis ist sehr zuverlässig und liefert die Zeitangaben, die direkt dem entsprechen, was auf dem Display zu sehen ist.

Da wir die Zeit nicht mehr selbst abfragen müssen, werden die Schritte WaitForLastPresention() und SampleTime() zu einem neuen Schritt zusammengefasst:

Unbekannter Blocktyp "codeBlock", bitte geben Sie einen Serializer dafür in der `serializers.types` prop an

Damit ist das Problem der unruhigen Bewegung gelöst.

Überlegungen zur Eingangslatenz

Die Eingangslatenz ist ein heikles Thema. Es ist nicht sehr einfach, dies genau zu messen, und es kann durch verschiedene Faktoren verursacht werden: Eingabe-Hardware, Betriebssystem, Treiber, Spiel-Engine, Spiel-Logik und die Anzeige. Hier konzentriere ich mich auf den Game-Engine-Faktor der Eingangslatenz, da Unity die anderen Faktoren nicht beeinflussen kann.

Die Eingabe-Latenzzeit ist die Zeit zwischen der Verfügbarkeit der OS-Eingabemeldung und der Übermittlung des Bildes an den Bildschirm. Mit der Haupt-Thread-Schleife können Sie die Eingangslatenz als Teil des Codes visualisieren (vorausgesetzt, QualitySettings.maxQueuedFrames ist auf 2 gesetzt):

Unbekannter Blocktyp "codeBlock", bitte geben Sie einen Serializer dafür in der `serializers.types` prop an

Puh, das war's! Zwischen dem Zeitpunkt, zu dem eine Eingabe als Betriebssystemnachricht verfügbar ist, und dem Zeitpunkt, zu dem die Ergebnisse auf dem Bildschirm sichtbar werden, passieren eine ganze Menge Dinge. Wenn Unity keine Frames fallen lässt und die von der Spielschleife verbrachte Zeit hauptsächlich aus Warten im Vergleich zur Verarbeitung besteht, ist das Worst-Case-Szenario der Eingabelatenz von der Engine für eine Bildwiederholfrequenz von 144 Hz 4 * 6,94 = 27,76 ms, weil wir darauf warten, dass die vorherigen Frames viermal auf dem Bildschirm erscheinen (d. h. vier Bildwiederholfrequenzintervalle).

Sie können die Latenzzeit verbessern, indem Sie Betriebssystemereignisse pumpen und die Eingabe aktualisieren , nachdem Sie gewartet haben, bis der vorherige Frame angezeigt wurde:

Unbekannter Blocktyp "codeBlock", bitte geben Sie einen Serializer dafür in der `serializers.types` prop an

Damit entfällt eine Wartezeit aus der Gleichung, und die Worst-Case-Eingangslatenz beträgt nun 3 * 6,94 = 20,82 ms.

Es ist möglich, die Eingangslatenz noch weiter zu reduzieren, indem QualitySettings.maxQueuedFrames auf Plattformen, die dies unterstützen, auf 1 reduziert wird. Dann sieht die Kette der Eingabeverarbeitung wie folgt aus:

Unbekannter Blocktyp "codeBlock", bitte geben Sie einen Serializer dafür in der `serializers.types` prop an

Die ungünstigste Eingabe-Latenzzeit beträgt also 2 * 6,94 = 13,88 ms. Dies ist der niedrigste Wert, den wir bei der Verwendung von VSync erreichen können.

Warnung: Wenn Sie QualitySettings.maxQueuedFrames auf 1 setzen, wird das Pipelining in der Engine im Wesentlichen deaktiviert, was es viel schwieriger macht, die angestrebte Bildrate zu erreichen. Denken Sie daran, dass bei einer niedrigeren Bildrate die Eingangslatenz wahrscheinlich schlechter ist, als wenn Sie QualitySettings.maxQueuedFrames auf 2 belassen. Wenn Sie z. B. auf 72 Bilder pro Sekunde heruntergehen, beträgt die Eingangslatenz 2 * 1⁄72 = 27,8 ms, was schlechter ist als die vorherige Latenz von 20,82 ms. Wenn Sie diese Einstellung nutzen möchten, empfehlen wir Ihnen, sie als Option zu Ihrem Spieleinstellungsmenü hinzuzufügen, damit Spieler mit schneller Hardware QualitySettings.maxQueuedFrames reduzieren können, während Spieler mit langsamerer Hardware die Standardeinstellung beibehalten können.

Auswirkungen von VSync auf die Eingangslatenz

Die Deaktivierung von VSync kann in bestimmten Situationen auch dazu beitragen, die Eingangslatenz zu verringern. Erinnern Sie sich daran, dass die Eingabe-Latenzzeit die Zeitspanne ist, die zwischen der Verfügbarkeit einer Eingabe durch das Betriebssystem und der Anzeige des Frames, der die Eingabe verarbeitet hat, auf dem Bildschirm vergeht, oder, als mathematische Gleichung:

Latenzzeit = tdisplay - tinput

Angesichts dieser Gleichung gibt es zwei Möglichkeiten, die Eingabelatenz zu verringern: entweder tdisplay niedriger einstellen (das Bild früher auf den Bildschirm bringen) oder tinput höher einstellen (Eingabeereignisse später abfragen).

Die Übertragung von Bilddaten von der GPU zur Anzeige ist extrem datenintensiv. Rechnen Sie einfach mal nach: Um ein 2560x1440 Nicht-HDR-Bild 144 Mal pro Sekunde an den Bildschirm zu senden, müssen 12,7 Gigabit pro Sekunde übertragen werden (24 Bit pro Pixel * 2560 * 1440 * 144). Diese Daten können nicht in einem Augenblick übertragen werden: Die GPU überträgt ständig Pixel an den Bildschirm. Nach jedem übertragenen Frame wird eine kurze Pause eingelegt, und die Übertragung des nächsten Frames beginnt. Diese Pausenzeit wird VBLANK genannt. Wenn VSync aktiviert ist, weisen Sie das Betriebssystem im Wesentlichen an, den Bildpuffer nur während VBLANK umzudrehen:

Rahmen

Wenn Sie VSync ausschalten, wird der hintere Puffer in den vorderen Puffer umgeschaltet, sobald das Rendern beendet ist. Das bedeutet, dass der Bildschirm plötzlich mitten in seinem Auffrischungszyklus mit der Aufnahme von Daten aus dem neuen Bild beginnt, wodurch der obere Teil des Bildes aus dem älteren Bild und der untere Teil des Bildes aus dem neueren Bild besteht:

Rahmen

Dieses Phänomen wird als "Zerreißen" bezeichnet. Mit Tearing kann die Anzeige für den unteren Teil des Bildes reduziert werden, wobei die visuelle Qualität und die flüssige Animation der Eingabe-Latenz geopfert werden. Dies ist besonders effektiv, wenn die Bildrate des Spiels niedriger ist als das VSync-Intervall, was eine teilweise Wiederherstellung der Latenz ermöglicht, die durch ein fehlendes VSync verursacht wird. Es ist auch effektiver in Spielen, bei denen der obere Teil des Bildschirms von der Benutzeroberfläche oder einer Skybox eingenommen wird, was es schwieriger macht, Tearing zu bemerken.

Die Deaktivierung von VSync kann auch dazu beitragen, die Eingabelatenz zu verringern, indem der Tinput erhöht wird. Wenn das Spiel in der Lage ist, mit einer viel höheren Bildrate als der Aktualisierungsrate zu rendern (z. B. mit 150 fps auf einem 60-Hz-Bildschirm), dann führt die Deaktivierung von VSync dazu, dass das Spiel OS-Ereignisse während jedes Aktualisierungsintervalls mehrmals pumpt, was die durchschnittliche Zeit, die sie in der OS-Eingabewarteschlange auf die Verarbeitung durch die Engine warten, reduziert.

Denken Sie daran, dass die Deaktivierung von VSync letztlich dem Spieler überlassen werden sollte, da es die visuelle Qualität beeinträchtigt und möglicherweise Übelkeit verursachen kann, wenn das Tearing spürbar wird. Es empfiehlt sich, eine Einstellungsoption in Ihrem Spiel vorzusehen, mit der Sie diese Funktion aktivieren/deaktivieren können, wenn sie von der Plattform unterstützt wird.

Fazit

Mit dieser Korrektur sieht die Frame-Timeline von Unity wie folgt aus:

Rahmen

Aber verbessert es tatsächlich die Geschmeidigkeit der Objektbewegung? Darauf können Sie wetten!

Wir haben die Unity 2020.1-Demo, die wir am Anfang dieses Beitrags gezeigt haben, in Unity 2020.2.0b1 ausgeführt. Hier ist das resultierende Zeitlupenvideo:

Dieser Fix ist in der 2020.2 Beta für diese Plattformen und Grafik-APIs verfügbar:

  • Windows, Xbox One, Universal Windows Platform (D3D11 und D3D12)
  • macOS, iOS, tvOS (Metall)
  • Playstation 4
  • Switch

Wir planen, dies in naher Zukunft auch für die übrigen von uns unterstützten Plattformen zu implementieren.

Verfolgen Sie diesen Forumsthread, um Updates zu erhalten, und lassen Sie uns wissen, was Sie von unserer bisherigen Arbeit halten.

Weitere Lektüre zum Thema Frame-Timing
Unity 2020.2 beta und darüber hinaus
Beta-Übersicht

Wenn Sie mehr darüber erfahren möchten, was in 2020.2 verfügbar ist, lesen Sie den Beta-Blogbeitrag und registrieren Sie sich für das Unity 2020.2 Beta-Webinar. Außerdem haben wir kürzlich unsere Pläne für 2021 vorgestellt.