Дивіться також цю відповідь .
Є два поширених способи використання Lerp:
1. Лінійне поєднання між початком і кінцем
progress = Mathf.Clamp01(progress + speedPerTick);
current = Mathf.Lerp(start, end, progress);
Це версія, яку ви, мабуть, найбільше знайомі.
2. Експоненціальна легкість до цілі
current = Mathf.Lerp(current, target, sharpnessPerTick);
Зауважте, що в цій версії currentзначення відображається і як вихід, і як вхід. Він зміщує startзмінну, тому ми завжди починаємо з того місця, куди ми переїхали в останнє оновлення. Саме це дає цій версії Lerpпам’яті від одного кадру до іншого. З цієї рухомої початкової точки потім переміщуємо частину відстані до targetпродиктованого sharpnessпараметром.
Цей параметр вже не зовсім "швидкий", тому що ми наближаємось до цілі, як у Зенона . Якби вони sharpnessPerTickбули 0.5, то під час першого оновлення ми б рухалися на півдорозі до своєї мети. Тоді під час наступного оновлення ми перемістимо половину відстані, що залишилася (тобто чверть нашої початкової відстані). Тоді на наступному ми знову переїдемо наполовину ...
Це дає "експоненціальне полегшення", коли рух швидкий, коли знаходиться далеко від мети і поступово сповільнюється, коли він наближається асимптотично (хоча з нескінченною точністю чисел він ніколи не досягне його в будь-якій кінцевій кількості оновлень - для наших цілей це наближається досить). Він відмінно підходить для переслідування рухомого цільового значення або згладжування галасливого введення, використовуючи " експоненціальну ковзну середню ", зазвичай, використовуючи дуже невеликий sharpnessPerTickпараметр типу 0.1або менший.
Але ви маєте рацію, у оновленій відповіді, на яку ви посилаєтесь, є помилка. Це не виправлення deltaTimeправильного шляху. Це дуже поширена помилка при використанні цього стилю Lerp.
Перший стиль Lerpлінійний, тому ми можемо лінійно регулювати швидкість, множивши на deltaTime:
progress = Mathf.Clamp01(progress + speedPerSecond * Time.deltaTime);
// or progress = Mathf.Clamp01(progress + Time.deltaTime / durationSeconds);
current = Mathf.Lerp(start, end, progress);
Але наше експоненціальне полегшення нелінійне , тому просто множення нашого sharpnessпараметра deltaTimeне дасть правильної корекції часу. Це відображатиметься як суддя в русі, якщо наша частота кадрів коливається, або зміна різкості ослаблення, якщо ви рухаєтесь від 30 до 60 послідовно.
Натомість нам потрібно застосувати експоненціальну корекцію для нашої експоненціальної легкості:
blend = 1f - Mathf.Pow(1f - sharpness, Time.deltaTime * referenceFramerate);
current = Mathf.Lerp(current, target, blend);
Ось referenceFramerateлише константа, як 30зберігати одиниці так sharpnessсамо, як ми використовували, перш ніж виправляти час.
У цьому коді є ще одна аргументована помилка, яка використовується Slerp- сферична лінійна інтерполяція є корисною, коли ми хочемо точно послідовної швидкості обертання через весь рух. Але якщо ми все одно Lerpбудемо використовувати нелінійну експоненціальну легкість, це дасть майже нерозрізний результат і дешевше. ;) Кватерніони лерп набагато краще, ніж матриці, тому зазвичай це безпечна заміна.