Vedi anche questa risposta .
Esistono due modi comuni per utilizzare Lerp:
1. Fusione lineare tra un inizio e una fine
progress = Mathf.Clamp01(progress + speedPerTick);
current = Mathf.Lerp(start, end, progress);
Questa è la versione con cui probabilmente hai più familiarità.
2. Facilità esponenziale verso un bersaglio
current = Mathf.Lerp(current, target, sharpnessPerTick);
Si noti che in questa versione il currentvalore appare sia come output sia come input. Sposta la startvariabile, quindi iniziamo sempre da dove ci siamo spostati sull'ultimo aggiornamento. Questo è ciò che dà questa versione di Lerpuna memoria da un frame all'altro. Da questo punto di partenza mobile, spostiamo quindi una frazione della distanza verso il targetdettato da un sharpnessparametro.
Questo parametro non è più una "velocità", perché ci avviciniamo al bersaglio in modo simile a Zenone . Se lo sharpnessPerTickfosse 0.5, al primo aggiornamento ci sposteremmo a metà del nostro obiettivo. Quindi al prossimo aggiornamento avremmo spostato metà della distanza rimanente (quindi un quarto della nostra distanza iniziale). Poi il prossimo ci sposteremmo di nuovo la metà ...
Ciò fornisce un "rilassamento esponenziale" in cui il movimento è veloce quando lontano dall'obiettivo e rallenta gradualmente mentre si avvicina in modo asintotico (sebbene con numeri a precisione infinita non lo raggiungerà mai in nessun numero finito di aggiornamenti - per i nostri scopi esso si avvicina abbastanza). È ottimo per inseguire un valore target mobile o per livellare un input rumoroso usando una " media mobile esponenziale ", di solito usando un sharpnessPerTickparametro molto piccolo come 0.1o più piccolo.
Ma hai ragione, c'è un errore nella risposta votata che colleghi. Non si corregge deltaTimenel modo giusto. Questo è un errore molto comune quando si utilizza questo stile di Lerp.
Il primo stile di Lerpè lineare, quindi possiamo regolare linearmente la velocità moltiplicando per deltaTime:
progress = Mathf.Clamp01(progress + speedPerSecond * Time.deltaTime);
// or progress = Mathf.Clamp01(progress + Time.deltaTime / durationSeconds);
current = Mathf.Lerp(start, end, progress);
Ma il nostro allentamento esponenziale non è lineare , quindi moltiplicare il nostro sharpnessparametro per deltaTimenon darà la corretta correzione temporale. Questo apparirà come un giudice nel movimento se il nostro framerate fluttua o un cambiamento nella nitidezza di attenuazione se passi costantemente da 30 a 60.
Invece dobbiamo applicare una correzione esponenziale per la nostra facilità esponenziale:
blend = 1f - Mathf.Pow(1f - sharpness, Time.deltaTime * referenceFramerate);
current = Mathf.Lerp(current, target, blend);
Ecco referenceFramerateuna costante come 30mantenere le unità per sharpnesslo stesso che stavamo usando prima di correggere il tempo.
C'è un altro errore discutibile in quel codice, che sta usando Slerp: l'interpolazione lineare sferica è utile quando vogliamo una velocità di rotazione esattamente coerente attraverso l'intero movimento. Ma se Lerputilizzeremo comunque una facilità esponenziale non lineare, si otterrà un risultato quasi indistinguibile ed è più economico. ;) I quaternioni sono molto meglio delle matrici, quindi di solito questa è una sostituzione sicura.