A mi entender, una función Lerp interpola entre dos valores ( a
y b
) usando un tercer valor ( t
) entre 0
y 1
. En t = 0
, se devuelve t = 1
el valor a , en , b
se devuelve el valor . A 0.5 se devuelve el valor a mitad de camino entre a
y b
.
(La siguiente imagen es un paso suave, generalmente una interpolación cúbica)
He estado navegando por los foros y en esta respuesta encontré la siguiente línea de código:transform.rotation = Quaternion.Slerp(transform.rotation, _lookRotation, Time.deltaTime);
Pensé para mí mismo, "qué tonto, no tiene idea", pero como tenía más de 40 votos a favor, lo probé y, efectivamente, ¡funcionó!
float t = Time.deltaTime;
transform.rotation = Quaternion.Slerp(transform.rotation, toRotation, t);
Debug.Log(t);
Tengo valores aleatorios entre 0.01
y 0.02
para t
. ¿No debería la función interpolar en consecuencia? ¿Por qué se acumulan estos valores? ¿Qué hay en lerp que no entiendo?
fuente
Respuestas:
Ver también esta respuesta .
Hay dos formas comunes de usar
Lerp
:1. Mezcla lineal entre un inicio y un final
Esta es la versión con la que probablemente estés más familiarizado.
2. Facilidad exponencial hacia un objetivo
Tenga en cuenta que en esta versión el
current
valor aparece como salida y como entrada. Desplaza lastart
variable, por lo que siempre comenzamos desde donde nos mudamos en la última actualización. Esto es lo que le da a esta versión deLerp
una memoria de un cuadro a otro. Desde este punto de partida en movimiento, luego movemos una fracción de la distancia hacia lotarget
dictado por unsharpness
parámetro.Este parámetro ya no es una "velocidad", porque nos acercamos al objetivo de una manera similar a Zeno . Si así
sharpnessPerTick
fuera0.5
, en la primera actualización nos moveríamos a la mitad de nuestro objetivo. Luego, en la próxima actualización, moveríamos la mitad de la distancia restante (un cuarto de nuestra distancia inicial). Luego, en el siguiente, nos moveríamos la mitad otra vez ...Esto proporciona una "facilidad exponencial" en la que el movimiento es rápido cuando está lejos del objetivo y se ralentiza gradualmente a medida que se acerca asintóticamente (aunque con números de precisión infinita nunca lo alcanzará en un número finito de actualizaciones, para nuestros propósitos se acerca lo suficiente). Es ideal para perseguir un valor objetivo en movimiento o para suavizar una entrada ruidosa usando un " promedio móvil exponencial ", generalmente usando un
sharpnessPerTick
parámetro muy pequeño como0.1
o más pequeño.Pero tienes razón, hay un error en la respuesta votada que vinculas. No está corrigiendo de
deltaTime
la manera correcta. Este es un error muy común al usar este estilo deLerp
.El primer estilo de
Lerp
es lineal, por lo que podemos ajustar linealmente la velocidad multiplicando pordeltaTime
:Pero nuestra flexibilización exponencial no es lineal , por lo que simplemente multiplicando nuestro
sharpness
parámetro pordeltaTime
no dará la corrección de tiempo correcta. Esto se mostrará como un factor decisivo en el movimiento si nuestro framerate fluctúa, o un cambio en la nitidez de flexibilización si pasa de 30 a 60 de manera constante.En cambio, necesitamos aplicar una corrección exponencial para nuestra facilidad exponencial:
Aquí
referenceFramerate
hay una constante como30
mantener las unidades parasharpness
lo mismo que estábamos usando antes de corregir el tiempo.Hay otro error discutible en ese código, que está utilizando
Slerp
: la interpolación lineal esférica es útil cuando queremos una velocidad de rotación exactamente consistente a través de todo el movimiento. Pero si vamos a utilizar una facilidad exponencial no lineal de todos modos,Lerp
dará un resultado casi indistinguible y es más barato. ;) Los cuaterniones son mucho mejores que las matrices, por lo que esta suele ser una sustitución segura.fuente
Creo que el concepto central que falta sería en este escenario A no está arreglado. A se actualiza con cada paso, independientemente de la interpolación que tenga Time.deltaTime.
Entonces, con A acercándose a B con cada paso, el espacio total de la interpolación cambia con cada llamada Lerp / Slerp. Sin hacer los cálculos reales, sospecharía que el efecto no es el mismo que el gráfico Smoothstep, pero es una forma económica de aproximar una desaceleración a medida que A se acerca a B.
Además, esto se usa con frecuencia porque B puede no ser estático tampoco. El caso típico podría ser una cámara que sigue a un jugador. Desea evitar sacudidas, haciendo que la cámara salte a una ubicación o rotación.
fuente
Tienes razón, el método
Quaternion Slerp(Quaternion a, Quaternion b, float t)
interpola entrea
yb
por la cantidadt
. Pero mire el primer valor, no es el valor inicial.Aquí el primer valor dado al método es la rotación actual del objeto
transform.rotation
. Entonces, para cada cuadro, se interpola entre la rotación actual y la rotación objetivo_lookRotation
por la cantidadTime.deltaTime
.Por eso produce una rotación suave.
fuente