Nach meinem Verständnis interpoliert eine Lerp-Funktion zwischen zwei Werten ( a
und b
) unter Verwendung eines dritten Werts ( t
) zwischen 0
und 1
. Bei t = 0
wird der Wert a zurückgegeben, bei t = 1
wird der Wert b
zurückgegeben. Bei 0,5 wird der Wert auf halbem Weg zwischen a
und b
zurückgegeben.
(Das folgende Bild ist ein sanfter Schritt, normalerweise eine kubische Interpolation.)
Ich habe die Foren durchsucht und bei dieser Antwort die folgende Codezeile gefunden:transform.rotation = Quaternion.Slerp(transform.rotation, _lookRotation, Time.deltaTime);
Ich dachte mir, "was für ein Idiot, er hat keine Ahnung", aber da es mehr als 40 Upvotes hatte, habe ich es ausprobiert und sicher hat es funktioniert!
float t = Time.deltaTime;
transform.rotation = Quaternion.Slerp(transform.rotation, toRotation, t);
Debug.Log(t);
Ich habe zufällige Werte zwischen 0.01
und 0.02
für t
. Sollte die Funktion nicht entsprechend interpolieren? Warum stapeln sich diese Werte? Was verstehe ich an Lerp nicht?
quelle
Antworten:
Siehe auch diese Antwort .
Es gibt zwei gängige Verwendungsmöglichkeiten
Lerp
:1. Lineare Überblendung zwischen Anfang und Ende
Dies ist die Version, mit der Sie wahrscheinlich am besten vertraut sind.
2. Exponentielle Leichtigkeit in Richtung eines Ziels
Beachten Sie, dass in dieser Version der
current
Wert sowohl als Ausgabe als auch als Eingabe angezeigt wird . Diestart
Variable wird verschoben , sodass wir immer dort beginnen, wo wir beim letzten Update umgezogen sind. Dies gibt dieser VersionLerp
eines Speichers von einem Frame zum nächsten. Von diesem beweglichen Startpunkt aus bewegen wir uns dann einen Bruchteil der Entfernung in Richtung destarget
durch einensharpness
Parameter vorgegebenen .Dieser Parameter ist keine "Geschwindigkeit" mehr, da wir uns dem Ziel auf Zeno-ähnliche Weise nähern . Wenn
sharpnessPerTick
ja0.5
, dann würden wir beim ersten Update auf halbem Weg zu unserem Ziel gehen. Beim nächsten Update würden wir dann die Hälfte der verbleibenden Distanz zurücklegen (also ein Viertel unserer ursprünglichen Distanz). Dann würden wir uns beim nächsten Mal wieder halb bewegen ...Dies führt zu einer "exponentiellen Lockerung", bei der die Bewegung weit vom Ziel entfernt schnell ist und sich bei asymptotischer Annäherung allmählich verlangsamt (obwohl sie mit Zahlen mit unendlicher Genauigkeit niemals in einer endlichen Anzahl von Aktualisierungen erreicht wird - für unsere Zwecke kommt nah genug heran). Es eignet sich hervorragend zum Verfolgen eines sich bewegenden Zielwerts oder zum Glätten einer verrauschten Eingabe mithilfe eines " exponentiellen gleitenden Durchschnitts ", normalerweise unter Verwendung eines sehr kleinen
sharpnessPerTick
Parameters wie0.1
oder kleiner.Aber Sie haben Recht, es gibt einen Fehler in der von Ihnen verlinkten Antwort. Es korrigiert nicht
deltaTime
den richtigen Weg. Dies ist ein sehr häufiger Fehler bei der Verwendung dieses Stils vonLerp
.Der erste Stil von
Lerp
ist linear, daher können wir die Geschwindigkeit linear anpassen, indem wir multiplizieren mitdeltaTime
:Unsere exponentielle Lockerung ist jedoch nicht linear . Wenn Sie also nur unseren
sharpness
Parameter mit multiplizierendeltaTime
, erhalten Sie keine korrekte Zeitkorrektur. Dies zeigt sich als Ruckeln in der Bewegung, wenn unsere Framerate schwankt, oder als Änderung der Lockerungsschärfe, wenn Sie konstant von 30 auf 60 gehen.Stattdessen müssen wir eine exponentielle Korrektur für unsere exponentielle Leichtigkeit anwenden:
Hier
referenceFramerate
ist nur eine Konstante30
, um die Einheiten aufsharpness
dem gleichen Stand zu halten, den wir vor der Zeitkorrektur verwendet haben.Es gibt einen weiteren möglichen Fehler in diesem Code, der verwendet wird
Slerp
: Die sphärische lineare Interpolation ist nützlich, wenn wir eine genau konsistente Rotationsrate über die gesamte Bewegung wünschen. Aber wenn wir sowieso eine nichtlineare exponentielle Leichtigkeit verwenden,Lerp
wird dies ein fast nicht unterscheidbares Ergebnis liefern und es ist billiger. ;) Quaternionen lerp viel besser als Matrizen, daher ist dies normalerweise eine sichere Substitution.quelle
Ich denke, das fehlende Kernkonzept wäre in diesem Szenario A nicht festgelegt. A wird mit jedem Schritt aktualisiert, unabhängig davon, wie viel Time.deltaTime interpoliert.
Wenn sich A mit jedem Schritt B nähert, ändert sich der Gesamtraum der Interpolation mit jedem Lerp / Slerp-Aufruf. Ohne die eigentliche Berechnung würde ich vermuten, dass der Effekt nicht mit Ihrem Smoothstep-Diagramm identisch ist, aber eine kostengünstige Methode ist, um eine Verzögerung zu approximieren, wenn A sich B nähert.
Dies wird auch häufig verwendet, da B möglicherweise auch nicht statisch ist. Ein typischer Fall könnte eine Kamera sein, die einem Spieler folgt. Sie möchten ein Ruckeln vermeiden, indem die Kamera zu einem Ort oder einer Drehung springt.
quelle
Sie haben Recht, die Methode
Quaternion Slerp(Quaternion a, Quaternion b, float t)
interpoliert zwischena
undb
um den Betragt
. Aber achten Sie auf den ersten Wert, es ist nicht der Startwert.Hier ist der erste Wert, der der Methode gegeben wird, die aktuelle Objektdrehung
transform.rotation
. Für jeden Frame wird also zwischen der aktuellen Drehung und der Zieldrehung_lookRotation
um den Betrag interpoliertTime.deltaTime
.Deshalb erzeugt es eine gleichmäßige Rotation.
quelle