Unterschied zwischen Update-Methode und FixedUpdate in Unity?

14

Ich fange an, Unity3d zu lernen und eine der Verwirrungen, die ich bekomme, ist der Unterschied zwischen Update()und FixedUpdate().

Ich verfolge Lynda Unity 2D - Spiele - Entwicklung Tutorial gibt, der Instruktor Anwendungen UpdateMethode, die Spieler RigidBody2D Komponente und Box - Collider hat, nutzt er die UpdateMethode , um die Spieler zu übersetzen, aber wenn ich in gleiche tun Updatedie Spieler nicht bewegen , aber wenn ich tun es FixedUpdatefunktioniert alles. Er gibt ein Tutorial aus Unity 4.3 und ich belege den Kurs in Unity 4.6.

Wo soll ich Updateund verwenden FixedUpdate?

Mönch
quelle

Antworten:

14

Ich wollte dies als Kommentar schreiben, aber es war ziemlich langwierig, also habe ich daraus eine Antwort gemacht.

Die aktuellen Antworten sind größtenteils richtig, aber ein paar Dinge, die erwähnt werden, sind irreführend / falsch.

Im Allgemeinen werden die meisten Aufgaben im Zusammenhang mit dem Spiel ausgeführt Update.

Zum Beispiel möchten Sie nicht nach Eingaben fragen FixedUpdate(nicht wegen der Leistung, sondern weil die Anrufe einfach nicht richtig funktionieren). AI fällt in dasselbe Boot.

Ständig aktualisierte Physik ist die einzige spielbezogene Aufgabe, FixedUpdatefür die es sich eignen sollte. Nicht kontinuierliche / gelegentliche Anrufe zu Dingen wie Physics.Raycastoder Rigidbody.AddForcegehören sogar dazu Update. Meine Erwähnung von Rigidbody.AddForcesteht anscheinend im Widerspruch zu dem, was in der Dokumentation impliziert werden könnte, aber der Schlüssel ist Continuous vs Non-continuous.

Ein großer Grund, warum nur kontinuierliche Physik dazugehört, FixedUpdateist die tatsächliche Natur von FixedUpdate. Andere Antworten haben erwähnt, wie FixedUpdate zu einem festen interval, but that's slightly misleading. In reality, a script is passed a time in Time.deltaTime/ Time.fixedDeltaTime* aufgerufen wird, der nicht direkt der tatsächlichen Zeit zwischen Anrufen entspricht, sondern der simulierten Zeit zwischen Anrufen.

(* Time.deltaTimeund Time.fixedDeltaTimesind der gleiche Wert, wenn sie in FixedUpdate[Unity kann erkennen, ob der aktuelle Anruf Time.deltaTimewährend entstanden ist FixedUpdateund zurückkehrt Time.fixedDeltaTime] aufgerufen werden. )

Natürlich kann derselbe Weg Updatewegen der unterschiedlichen Leistung auch nicht konstant aufgerufen werden FixedUpdate. Der Hauptunterschied besteht darin, dass jeder Frame, FixedUpdateder nicht oft genug aufgerufen wurde, um das richtige Intervall zwischen Anrufen zu ermitteln, mehrmals aufgerufen wird (oder nicht aufgerufen wird , wenn der Durchschnitt zu hoch ist). In den Dokumenten zur Ausführungsreihenfolge heißt es, dass FixedUpdate mehrmals in einem Frame aufgerufen werden kann:

... FixedUpdate: FixedUpdate wird häufig häufiger aufgerufen als Update. Es kann mehrere Male pro Frame aufgerufen werden, wenn die Framerate niedrig ist, und es kann überhaupt nicht zwischen Frames aufgerufen werden, wenn die Framerate hoch ist ...

Dies wirkt sich nicht auf die Physik aus, da der Rest der Ausführungsreihenfolge und die Engine so gut wie alles andere, was Sie eingeben FixedUpdate, betroffen ist und Probleme verursacht.

Wenn Sie z. B. die AI-Verarbeitung einbinden FixedUpdate, besteht kein Grund anzunehmen, dass die AI keine Aktualisierungen für mehrere Frames hintereinander überspringt. Jedes Mal, wenn `FixedUpdate ins Hintertreffen gerät, wird Ihre KI mehrere Male in einem einzigen Frame aktualisiert, bevor Dinge wie Physik und Eingaben / Bewegungen von Spielern verarbeitet werden um Fehler und unberechenbares Verhalten aufzuspüren.

Wenn Sie in einem festen Intervall etwas tun müssen, verwenden Sie andere von Unity bereitgestellte Methoden wie Coroutinesund InvokeRepeating.

Und ein kleiner Hinweis zu Time.deltaTimeund wann man es benutzt:

Der einfachste Weg, um den Effekt von Time.deltaTime zu beschreiben, besteht darin, eine Zahl von Einheit pro Frame in Einheit pro Sekunde zu ändern . Wenn Sie beispielsweise ein Skript wie transform.Translate(Vector3.up * 5)in Update haben, verschieben Sie die Transformation im Wesentlichen mit einer Geschwindigkeit von 5 Metern pro Frame . Das heißt, wenn die Framerate niedrig ist, ist die Bewegung langsamer und wenn die Framerate hoch ist, ist die Bewegung schneller.

Wenn Sie denselben Code verwenden und in ändern, transform.Translate(Vector3.up * 5 * Time.deltaTime)wird das Objekt mit einer Geschwindigkeit von 5 Metern pro Sekunde bewegt . Das bedeutet, dass sich das Objekt unabhängig von der Framerate 5 Meter pro Sekunde bewegt (je langsamer die Framerate ist, desto sprunghafter wird die Bewegung des Objekts, da es sich alle X Sekunden immer noch um den gleichen Betrag bewegt).

Im Allgemeinen möchten Sie, dass Ihre Bewegung pro Sekunde erfolgt. Auf diese Weise verhält sich Ihre Physik / Bewegung unabhängig von der Geschwindigkeit des Computers genauso, und auf langsameren Geräten treten keine seltsamen Fehler auf.

Und es hat keinen Sinn, es zu verwenden FixedUpdate. Aufgrund dessen, was ich oben erwähnt habe, erhalten Sie bei jedem Aufruf den gleichen Wert (den Wert für den festen Aktualisierungszeitschritt), und Ihre Werte werden dadurch nicht beeinträchtigt. Die in definierte Bewegung / Physik FixedUpdatewird bereits in Einheiten pro Sekunde angegeben, sodass Sie sie nicht benötigen.

Selali Adobor
quelle
4

Die UpdateFunktion wird bei jedem Frame aufgerufen. Die Häufigkeit hängt davon ab, wie schnell der Computer Bilder rendern kann. Wird auf einem langsameren Computer Updateweniger häufig aufgerufen als auf einem schnelleren. Wenn Sie zeitbasierte Berechnungen durchführen, können Sie sie normalisieren, indem Time.deltaTimeSie angeben, wie lange es her ist, seit das letzte Mal Updateaufgerufen wurde (Vorbehalte gelten).
Sie werden in der Regel verwendet Update, um anzeigebezogene Aufgaben auszuführen (z. B. Aktualisieren eines Oberflächenelements).

Die FixedUpdateFunktion wird in festen Intervallen aufgerufen. Unabhängig davon, wie oft das Bild aktualisiert FixedUpdatewird, werden die 1/Time.fixedDeltaTimeAufrufe in der Sekunde vorgenommen.
Sie werden im Allgemeinen verwendet FixedUpdate, um Aufgaben im Zusammenhang mit dem Gameplay auszuführen (z. B. Aktualisieren der Physik).

3Doubloons
quelle
Ist dies eine Alternative zur Multiplikation mit Time.delta? Gibt es einen Grund, den einen oder anderen zu benutzen?
Ben
@Ben sie haben zwei verschiedene Ziele und Sie sollten die richtige Funktion für das, was Sie tun, verwenden.
o0 '.
@Lohoris Sorry, ich meinte, gibt es einen Grund, FixedUpdate über Update zu verwenden und Dinge mit Time.deltaTime zu multiplizieren, um sie rahmenunabhängig zu machen?
Ben
@Ben ja, Präzision. In einem System mit langsamem Rendering wird es Updateimmer seltener aufgerufen, und Ihre Simulation leidet stark darunter. Sie werden es vielleicht nicht bemerken, während die Simulation einfach ist, aber sie wird leicht schrecklich brechen, wenn es nicht so ist.
o0 '.
1
@Ben nein: Wenn Sie eine präzise Simulation wünschen, müssen Sie viele kleine Schritte ausführen, keine großen, die jedes Mal zufällig größer oder kleiner sind. Und nein, der springende Punkt von FixedUpdate ist, dass es so oft aufgerufen wird, ohne dass Fragen gestellt werden.
o0 '.
2

Von: http://unity3d.com/learn/tutorials/modules/beginner/scripting/update-and-fixedupdate

Der in FixedUpdate verwendete Zeitschritt ist nicht variabel.

Wenn Ihr Spiel zu verzögern beginnt, wenn es aufholt, möchten Sie nicht mehr als 10 Sekunden Physik in einem Update, daher wird es normalerweise in FixedUpdate ausgeführt, das in einem festen Intervall aufgerufen wird.

Beispielsweise:

Update(float elapsedSeconds)
{
  Position += Velocity * 34.23423; //Windows Update is self-important
}
FixedUpdate(float elapsedSeconds)
{
  Position += Velocity * 0.0166; //60fps
}

Wo:

Update(34.23423)

==

FixedUpdate(10.0)
FixedUpdate(10.0)
FixedUpdate(10.0)
//4.23423 + 5.76577 game-seconds later...
FixedUpdate(10.0)
Jon
quelle
Ich habe das in meiner Antwort erwähnt, aber FixedUpdatenicht in einem festen Intervall angerufen. Die eigentliche Natur FixedUpdateist es, mehrere Physikzyklen in einem Frame zusammenzufassen, wenn Ihr Spiel zu verzögern beginnt, und Zyklen zu überspringen, wenn es zu schnell läuft, damit der Durchschnitt zum festen Aktualisierungszeitschritt passt. Unity ist kein Multithreading-System, daher gibt es keine Möglichkeit, FixedUpdate-Aufrufe in einem festen Intervall zu garantieren (was passiert, wenn ein FixedUpdate zu lange dauert). Selbst wenn es so wäre, wäre es wahrscheinlich immer noch so gut wie unmöglich.
Selali Adobor
Den meisten [Unity?] - Benutzern ist nicht bekannt, dass Render / Update / FixedUpdate alle über eine einzige Rückrufmethode aufgerufen werden. Danke für deinen Einsatz!
Jon
2

Updatewird so schnell wie möglich angerufen. Die Variable 'Time.deltaTime' wird auf die tatsächliche Zeit eingestellt, die seit dem letzten Aufruf vergangen ist. Wenn Verzögerung oder ähnliches das Spiel verlangsamt, Updatewird dies immer noch nur einmal aufgerufen, sobald die Verzögerung vorbei ist, mit einem hohen Wert von deltaTime.

FixedUpdatewird in regelmäßigen Abständen aufgerufen. Es wird niemals öfter aufgerufen als in 'Time.fixedDeltaTime' angegeben. Wenn Verzögerung oder ähnliches das Spiel verlangsamt, FixedUpdatewird es mehrmals kurz hintereinander aufgerufen, damit das Spiel aufholt. Time.deltaTimewird gleich gesetzt, Time.fixedDeltaTimebevor ausgeführt FixedUpdatewird, dies ist jedoch nur ein Trick, um die Migration von Code zwischen den beiden zu vereinfachen.

Im Allgemeinen Updatesollte für interpolierbares Verhalten und FixedUpdatefür Verhalten verwendet werden, die schrittweise berechnet werden müssen oder von denen abhängen, die dies tun, z. B. physikbasierte Bewegung. Wenn Sie irgendeine Art von Schleife Updateentlang der Linien für schreiben for(time=0;time<=deltaTime;time+=someStep)..., sollten Sie dies wahrscheinlich stattdessen in FixedUpdate tun.

Mark Green
quelle