Ayrıca bu cevaba bakınız .
Kullanmanın iki yaygın yolu vardır Lerp
:
1. Başlangıç ve bitiş arasında doğrusal karıştırma
progress = Mathf.Clamp01(progress + speedPerTick);
current = Mathf.Lerp(start, end, progress);
Bu muhtemelen en tanıdığınız sürümdür.
2. Hedefe doğru üstel kolaylık
current = Mathf.Lerp(current, target, sharpnessPerTick);
Not Bu sürümde bu current
değer çıkışı hem olarak görünür ve bir girdi. Değişkeni değiştirir start
, bu yüzden her zaman son güncellemeye taşındığımız yerden başlıyoruz. Lerp
Belleğin bu sürümünü bir kareden diğerine veren şey budur . Bu hareketli başlangıç noktasından sonra, mesafenin bir kısmını target
bir sharpness
parametre tarafından dikte edilen yöne doğru hareket ettiririz .
Bu parametre artık bir "hız" değil, çünkü hedefe Zeno benzeri bir şekilde yaklaşıyoruz . Eğer sharpnessPerTick
idi 0.5
, daha sonra ilk güncelleme biz hedefimize yarıya taşımak istiyorum. Sonra bir sonraki güncellemede kalan mesafenin yarısını hareket ettiririz (başlangıç mesafemizin dörtte biri). Sonra bir sonraki yarıyı tekrar hareket ettirirdik ...
Bu, hareketin hedeften uzak olduğunda hızlı olduğu ve asimptotik olarak yaklaştıkça kademeli olarak yavaşladığı "üstel bir rahatlık" verir (sonsuz hassasiyetli sayılarla hiçbir zaman sınırlı sayıda güncellemede ona ulaşmaz - bizim amacımız için) yeterince yakınlaşır). Hareketli bir hedef değeri kovalamak veya " üstel hareketli ortalama " kullanarak gürültülü bir girişi düzeltmek , genellikle çok küçük veya çok küçük bir sharpnessPerTick
parametre kullanarak mükemmeldir 0.1
.
Ama haklısın, yukarı doğru cevap verdiğiniz bağlantıda bir hata var. O için düzeltme değil deltaTime
doğru şekilde. Bu stili kullanırken çok yaygın bir hatadır Lerp
.
İlk stili Lerp
doğrusaldır, bu nedenle hızı çarparak doğrusal olarak ayarlayabiliriz deltaTime
:
progress = Mathf.Clamp01(progress + speedPerSecond * Time.deltaTime);
// or progress = Mathf.Clamp01(progress + Time.deltaTime / durationSeconds);
current = Mathf.Lerp(start, end, progress);
Ancak üstel genişlememiz doğrusal değildir , bu nedenle sharpness
parametremizi çarpmak deltaTime
doğru zaman düzeltmesini vermeyecektir. Bu, kare hızımız dalgalanırsa harekette bir titreme veya 30'dan 60'a sürekli olarak giderseniz hareket hızı keskinliğinde bir değişiklik olarak görünecektir.
Bunun yerine, üstel kolaylığımız için üstel bir düzeltme uygulamamız gerekir:
blend = 1f - Mathf.Pow(1f - sharpness, Time.deltaTime * referenceFramerate);
current = Mathf.Lerp(current, target, blend);
Burada referenceFramerate
, zaman düzeltmeden önce 30
üniteleri kullandığımız gibi tutmak gibi bir sabit var sharpness
.
Bu kodda başka bir tartışmalı hata daha var Slerp
- küresel doğrusal enterpolasyon, tüm hareket boyunca tam olarak tutarlı bir dönüş hızı istediğimizde yararlıdır. Ama yine de doğrusal olmayan bir üstel kolaylık Lerp
kullanacaksak, neredeyse ayırt edilemez bir sonuç verecektir ve daha ucuzdur. ;) Kuaterniyonlar matrislerden çok daha iyi ler, bu yüzden bu genellikle güvenli bir ikame.