Lihat juga jawaban ini .
Ada dua cara umum untuk digunakan Lerp
:
1. Pencampuran linier antara awal dan akhir
progress = Mathf.Clamp01(progress + speedPerTick);
current = Mathf.Lerp(start, end, progress);
Ini adalah versi yang mungkin paling Anda kenal.
2. Kemudahan eksponensial menuju target
current = Mathf.Lerp(current, target, sharpnessPerTick);
Perhatikan bahwa dalam versi ini current
nilai muncul sebagai output dan input. Itu menggeser start
variabel, jadi kami selalu mulai dari mana pun kami pindah ke pada pembaruan terakhir. Inilah yang memberikan versi Lerp
memori ini dari satu frame ke yang berikutnya. Dari titik awal yang bergerak ini, kami kemudian memindahkan sebagian kecil dari jarak ke arah yang target
ditentukan oleh sharpness
parameter.
Parameter ini bukan "kecepatan" lagi, karena kami mendekati target dengan cara yang mirip Zeno . Jika sharpnessPerTick
berada 0.5
, maka pada update pertama kami akan pindah setengah jalan untuk tujuan kami. Kemudian pada pembaruan berikutnya kami akan memindahkan setengah jarak yang tersisa (jadi seperempat dari jarak awal kami). Kemudian pada berikutnya kita akan bergerak setengah lagi ...
Ini memberikan "pelonggaran eksponensial" di mana gerakannya cepat ketika jauh dari target dan secara bertahap melambat ketika mendekati asimtotik (meskipun dengan angka presisi tak terbatas, ia tidak akan pernah mencapainya dalam jumlah pembaruan terbatas - untuk keperluan kami, cukup dekat). Ini bagus untuk mengejar nilai target bergerak, atau menghaluskan input berisik menggunakan " moving average eksponensial ," biasanya menggunakan sharpnessPerTick
parameter yang sangat kecil suka 0.1
atau lebih kecil.
Tapi Anda benar, ada kesalahan dalam jawaban yang Anda jawab tautannya. Itu tidak mengoreksi deltaTime
dengan cara yang benar. Ini adalah kesalahan yang sangat umum ketika menggunakan gaya Lerp
.
Gaya pertama Lerp
adalah linear, jadi kami dapat menyesuaikan kecepatan secara linear dengan mengalikannya dengan deltaTime
:
progress = Mathf.Clamp01(progress + speedPerSecond * Time.deltaTime);
// or progress = Mathf.Clamp01(progress + Time.deltaTime / durationSeconds);
current = Mathf.Lerp(start, end, progress);
Tapi pelonggaran eksponensial kami adalah non-linear , jadi hanya mengalikan sharpness
parameter kami dengan deltaTime
tidak akan memberikan koreksi waktu yang benar. Ini akan muncul sebagai juri dalam gerakan jika framerate kami berfluktuasi, atau perubahan dalam ketajaman pelonggaran jika Anda beralih dari 30 menjadi 60 secara konsisten.
Sebaliknya kita perlu menerapkan koreksi eksponensial untuk kemudahan eksponensial kita:
blend = 1f - Mathf.Pow(1f - sharpness, Time.deltaTime * referenceFramerate);
current = Mathf.Lerp(current, target, blend);
Berikut referenceFramerate
ini adalah konstanta yang ingin 30
menjaga unit tetap sharpness
sama seperti yang kami gunakan sebelum mengoreksi waktu.
Ada satu kesalahan lain yang bisa diperdebatkan dalam kode itu, yang menggunakan Slerp
- interpolasi linear bola berguna ketika kita menginginkan tingkat rotasi yang persis konsisten melalui seluruh gerakan. Tetapi jika kita akan menggunakan kemudahan eksponensial non-linear, Lerp
akan memberikan hasil yang hampir tidak dapat dibedakan dan lebih murah. ;) Kuotaerner lebih baik daripada matriks, jadi ini biasanya pengganti yang aman.