Siehe auch diese Antwort .
Es gibt zwei gängige Verwendungsmöglichkeiten Lerp
:
1. Lineare Überblendung zwischen Anfang und Ende
progress = Mathf.Clamp01(progress + speedPerTick);
current = Mathf.Lerp(start, end, progress);
Dies ist die Version, mit der Sie wahrscheinlich am besten vertraut sind.
2. Exponentielle Leichtigkeit in Richtung eines Ziels
current = Mathf.Lerp(current, target, sharpnessPerTick);
Beachten Sie, dass in dieser Version der current
Wert sowohl als Ausgabe als auch als Eingabe angezeigt wird . Die start
Variable wird verschoben , sodass wir immer dort beginnen, wo wir beim letzten Update umgezogen sind. Dies gibt dieser Version Lerp
eines Speichers von einem Frame zum nächsten. Von diesem beweglichen Startpunkt aus bewegen wir uns dann einen Bruchteil der Entfernung in Richtung des target
durch einen sharpness
Parameter vorgegebenen .
Dieser Parameter ist keine "Geschwindigkeit" mehr, da wir uns dem Ziel auf Zeno-ähnliche Weise nähern . Wenn sharpnessPerTick
ja 0.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 wie 0.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 von Lerp
.
Der erste Stil von Lerp
ist linear, daher können wir die Geschwindigkeit linear anpassen, indem wir multiplizieren mit deltaTime
:
progress = Mathf.Clamp01(progress + speedPerSecond * Time.deltaTime);
// or progress = Mathf.Clamp01(progress + Time.deltaTime / durationSeconds);
current = Mathf.Lerp(start, end, progress);
Unsere exponentielle Lockerung ist jedoch nicht linear . Wenn Sie also nur unseren sharpness
Parameter mit multiplizieren deltaTime
, 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:
blend = 1f - Mathf.Pow(1f - sharpness, Time.deltaTime * referenceFramerate);
current = Mathf.Lerp(current, target, blend);
Hier referenceFramerate
ist nur eine Konstante 30
, um die Einheiten auf sharpness
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.