À ma connaissance, une fonction Lerp interpole entre deux valeurs ( a
et b
) en utilisant une troisième valeur ( t
) entre 0
et 1
. À t = 0
, la valeur a est renvoyée, à t = 1
, la valeur b
est renvoyée. À 0,5, la valeur à mi-chemin entre a
et b
est renvoyée.
(L'image suivante est une étape lisse, généralement une interpolation cubique)
J'ai parcouru les forums et sur cette réponse, j'ai trouvé la ligne de code suivante:transform.rotation = Quaternion.Slerp(transform.rotation, _lookRotation, Time.deltaTime);
Je me suis dit: "quel idiot, il n'a aucune idée" mais comme il y avait plus de 40 votes positifs, j'ai essayé et bien sûr, cela a fonctionné!
float t = Time.deltaTime;
transform.rotation = Quaternion.Slerp(transform.rotation, toRotation, t);
Debug.Log(t);
J'ai obtenu des valeurs aléatoires entre 0.01
et 0.02
pour t
. La fonction ne devrait-elle pas interpoler en conséquence? Pourquoi ces valeurs se cumulent-elles? Qu'est-ce que le lerp que je ne comprends pas?
la source
Réponses:
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
C'est la version que vous connaissez probablement le mieux.
2. Facilité exponentielle vers une cible
Notez que dans cette version, la
current
valeur apparaît à la fois comme sortie et comme entrée. Il déplace lastart
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 celletarget
dictée par unsharpness
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 cas0.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 comme0.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 deLerp
.Le premier style de
Lerp
est linéaire, nous pouvons donc ajuster linéairement la vitesse en multipliant pardeltaTime
:Mais notre assouplissement exponentiel n'est pas linéaire , donc multiplier simplement notre
sharpness
paramètre pardeltaTime
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:
Voici
referenceFramerate
juste une constante comme30
garder les unités poursharpness
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.la source
Je pense que le concept de base manquant serait dans ce scénario A n'est pas fixe. A est mis à jour à chaque étape, quelle que soit l'interpolation de Time.deltaTime.
Ainsi, avec A se rapprochant de B à chaque étape, l'espace total de l'interpolation change avec chaque appel Lerp / Slerp. Sans faire le calcul, je soupçonne que l'effet n'est pas le même que votre graphique Smoothstep, mais est un moyen bon marché d'approximer une décélération lorsque A se rapproche de B.
En outre, cela est fréquemment utilisé car B peut ne pas être statique non plus. Le cas typique peut être une caméra qui suit un joueur. Vous voulez éviter les secousses, en faisant sauter la caméra vers un emplacement ou une rotation.
la source
Vous avez raison, la méthode
Quaternion Slerp(Quaternion a, Quaternion b, float t)
interpole entrea
etb
par le montantt
. Mais regardez la première valeur, ce n'est pas la valeur de départ.Ici, la première valeur donnée à la méthode est la rotation actuelle de l'objet
transform.rotation
. Ainsi, pour chaque image, il interpole entre la rotation actuelle et la rotation cible_lookRotation
de la quantitéTime.deltaTime
.C'est pourquoi il produit une rotation douce.
la source