Voir aussi cette réponse .
Il existe deux façons courantes d'utiliser Lerp
:
1. Mélange linéaire entre un début et une fin
progress = Mathf.Clamp01(progress + speedPerTick);
current = Mathf.Lerp(start, end, progress);
C'est la version que vous connaissez probablement le mieux.
2. Facilité exponentielle vers une cible
current = Mathf.Lerp(current, target, sharpnessPerTick);
Notez que dans cette version, la current
valeur apparaît à la fois comme sortie et comme entrée. Il déplace la start
variable, nous partons donc toujours de l'endroit où nous nous sommes déplacés lors de la dernière mise à jour. C'est ce qui donne cette version d' Lerp
une mémoire d'une image à l'autre. À partir de ce point de départ en mouvement, nous déplaçons ensuite une fraction de la distance vers celle target
dictée par un sharpness
paramètre.
Ce paramètre n'est plus tout à fait une "vitesse", car nous approchons la cible d'une manière zéno . Si tel sharpnessPerTick
était le cas 0.5
, lors de la première mise à jour, nous irions à mi-chemin de notre objectif. Ensuite, lors de la prochaine mise à jour, nous déplacerions la moitié de la distance restante (donc un quart de notre distance initiale). Ensuite, le lendemain, nous bougions à nouveau de moitié ...
Cela donne une "facilité exponentielle" où le mouvement est rapide lorsqu'il est loin de la cible et ralentit progressivement à mesure qu'il approche asymptotiquement (bien qu'avec des nombres de précision infinie, il ne l'atteindra jamais dans un nombre fini de mises à jour - pour nos besoins, il se rapproche suffisamment). C'est idéal pour chasser une valeur cible mobile ou lisser une entrée bruyante en utilisant une " moyenne mobile exponentielle ", en utilisant généralement un très petit sharpnessPerTick
paramètre comme 0.1
ou plus petit.
Mais vous avez raison, il y a une erreur dans la réponse votée que vous liez. Ce n'est pas corriger pour deltaTime
la bonne façon. Il s'agit d'une erreur très courante lors de l'utilisation de ce style de Lerp
.
Le premier style de Lerp
est linéaire, nous pouvons donc ajuster linéairement la vitesse en multipliant par deltaTime
:
progress = Mathf.Clamp01(progress + speedPerSecond * Time.deltaTime);
// or progress = Mathf.Clamp01(progress + Time.deltaTime / durationSeconds);
current = Mathf.Lerp(start, end, progress);
Mais notre assouplissement exponentiel n'est pas linéaire , donc multiplier simplement notre sharpness
paramètre par deltaTime
ne donnera pas la correction temporelle correcte. Cela apparaîtra comme un tremblement dans le mouvement si notre cadence fluctue, ou un changement dans la netteté de l'assouplissement si vous passez de 30 à 60 de manière cohérente.
Au lieu de cela, nous devons appliquer une correction exponentielle pour notre facilité exponentielle:
blend = 1f - Mathf.Pow(1f - sharpness, Time.deltaTime * referenceFramerate);
current = Mathf.Lerp(current, target, blend);
Voici referenceFramerate
juste une constante comme 30
garder les unités pour sharpness
la même chose que nous utilisions avant de corriger le temps.
Il y a une autre erreur discutable dans ce code, qui utilise Slerp
- l'interpolation linéaire sphérique est utile lorsque nous voulons un taux de rotation exactement cohérent tout au long du mouvement. Mais si nous allons utiliser une facilité exponentielle non linéaire de toute façon, Lerp
cela donnera un résultat presque impossible à distinguer et c'est moins cher. ;) Les quaternions lerp beaucoup mieux que les matrices, c'est donc généralement une substitution sûre.