Ver también esta respuesta .
Hay dos formas comunes de usar Lerp:
1. Mezcla lineal entre un inicio y un final
progress = Mathf.Clamp01(progress + speedPerTick);
current = Mathf.Lerp(start, end, progress);
Esta es la versión con la que probablemente estés más familiarizado.
2. Facilidad exponencial hacia un objetivo
current = Mathf.Lerp(current, target, sharpnessPerTick);
Tenga en cuenta que en esta versión el currentvalor aparece como salida y como entrada. Desplaza la startvariable, por lo que siempre comenzamos desde donde nos mudamos en la última actualización. Esto es lo que le da a esta versión de Lerpuna memoria de un cuadro a otro. Desde este punto de partida en movimiento, luego movemos una fracción de la distancia hacia lo targetdictado por un sharpnessparámetro.
Este parámetro ya no es una "velocidad", porque nos acercamos al objetivo de una manera similar a Zeno . Si así sharpnessPerTickfuera 0.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 sharpnessPerTickparámetro muy pequeño como 0.1o más pequeño.
Pero tienes razón, hay un error en la respuesta votada que vinculas. No está corrigiendo de deltaTimela manera correcta. Este es un error muy común al usar este estilo de Lerp.
El primer estilo de Lerpes lineal, por lo que podemos ajustar linealmente la velocidad multiplicando por deltaTime:
progress = Mathf.Clamp01(progress + speedPerSecond * Time.deltaTime);
// or progress = Mathf.Clamp01(progress + Time.deltaTime / durationSeconds);
current = Mathf.Lerp(start, end, progress);
Pero nuestra flexibilización exponencial no es lineal , por lo que simplemente multiplicando nuestro sharpnessparámetro por deltaTimeno 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:
blend = 1f - Mathf.Pow(1f - sharpness, Time.deltaTime * referenceFramerate);
current = Mathf.Lerp(current, target, blend);
Aquí referenceFrameratehay una constante como 30mantener las unidades para sharpnesslo 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, Lerpdará 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.