Çarpma işlemi
En azından Birliğin Kuaterniyonları uygulaması açısından, soruda açıklanan çarpım sırası doğru değil. Bu önemlidir, çünkü 3D döndürme değişmeli değildir .
Yani, bir nesneyi rotationChange
başından başlayarak döndürmek currentOrientation
istersem, şöyle yazarım:
Quaternion newOrientation = rotationChange * currentOrientation;
(yani, Dönüşümler sola yığılır - Unity'nin matris sözleşmesiyle aynıdır. En sağdaki dönüş ilk / "en yerel" uçta uygulanır)
Bir yönü veya ofseti bir vektörü döndürerek dönüştürmek isteseydim, şöyle yazarım:
Vector3 rotatedOffsetVector = rotationChange * currentOffsetVector;
(Aksini yaparsanız Birlik derleme hatası üretecektir)
harmanlama
Çoğu durumda Lerping rotasyonları ile kurtulabilirsiniz. Açısı quaternion içinde "gizli olarak" kullanılacaktır en olmasıdır yarım bir Matrix gibi bir şey daha LERP doğrusal yaklaşım büyük ölçüde yakın yapma, dönme açısı (genelde will not LERP iyi!). Daha fazla açıklama için bu videoya yaklaşık 40 dakika göz atın .
Gerçekten Slerp'e ihtiyaç duyduğunuz durumlardan biri, bir animasyon zaman çizelgesindeki anahtar kareler arasında enterpolasyon yapmak gibi zaman içinde tutarlı hıza ihtiyacınız olduğundadır. Bir çıkışın iki giriş arasında orta olmasına özen gösterdiğiniz durumlarda (bir animasyonun karışım katmanları gibi) o zaman genellikle Lerp oldukça iyi hizmet eder.
Başka?
İççarpım Eğer rotasyonlar karşılaştırmak gerekirse benzerlik ölçüsü olarak nokta ürününü kullanabilirsiniz böylece iki birim kuaterniyonların, aralarındaki açının kosinüs verir. Bu biraz belirsizdir, bu yüzden daha okunaklı kod için sık sık Quaternion kullanırdım.Angle (a, b) , ki bu, açıları karşılaştırdığımızı, açıkça bilinen birimler (derece) cinsinden ifade eder.
Birliğin Kuaterniyonlar için sağladığı bu kolaylık metot tipleri çok faydalıdır. Hemen hemen her projede bunu en az birkaç kez kullanıyorum :
Quaternion.LookRotation(Vector3 forward, Vector3 up)
Bu, şöyle bir kuaterniyon oluşturur:
- Yerel z + eksenini tam olarak
forward
vektör bağımsız değişkeni boyunca gösterecek şekilde döndürür
- Yerel y + eksenini
up
, varsa vektör argümanına veya (0, 1, 0)
varsa ihmal edildiğinde mümkün olduğu kadar yakın noktaya döndürür
"Yukarı" sadece "olabildiğince yakın" olmasının sebebi sistemin fazla önceden tanımlanmış olmasıdır. Z + 'ya karşı karşıya kalmak forward
, iki derece serbestlik kullanmaktır (örneğin, yalpa ve zift);
Oldukça sık buluyorum ki tam tersi özelliklere sahip bir şey istiyorum: yerel y + 'nin tam olarak işaret etmesini up
ve yerel z +' forward
nın kalan özgürlüğe mümkün olduğunca yaklaşmasını istiyorum .
Bu, örneğin, hareket girişi için kamera-göreli bir koordinat çerçevesi oluşturmaya çalışırken ortaya çıkar: Yerel yukarı yönümün zemine dik ya da eğimli yüzeye normal kalmasını istiyorum, bu yüzden girişim karakteri araziye sokmaya çalışmıyor veya onları havaya kaldırmak.
Bunu ayrıca, bir tankın kulenin mahfazasının bir hedefle yüzleşmesini istiyorsanız, yukarı / aşağı hedef alırken tankın gövdesinden ayrılmadan da alabilirsiniz.
LookRotation
Ağır kaldırma için bunu kullanarak kendi rahatlık fonksiyonumuzu oluşturabiliriz :
Quaternion TurretLookRotation(Vector3 approximateForward, Vector3 exactUp)
{
Quaternion rotateZToUp = Quaternion.LookRotation(exactUp, -approximateForward);
Quaternion rotateYToZ = Quaternion.Euler(90f, 0f, 0f);
return rotateZToUp * rotateYToZ;
}
Burada yerel y + 'dan z +' ya ve yerel z + 'y' y 'yi döndürür.
Sonra yeni z + 'yı yukarı yönümüze döndürüyoruz (bu nedenle net sonuç doğrudan y yerel noktalarıdır exactUp
) ve yeni y + olumsuz yöndeki ileri yöne mümkün olduğunca yakındır (bu nedenle net sonuç, mümkün olduğu kadar yerel z + noktalarıdır. approximateForward
)
Bir başka kullanışlı kolaylık yöntemi de Quaternion.RotateTowards
, sıklıkla kullandığım:
Quaternion newRotation = Quaternion.RotateTowards(
oldRotation,
targetRotation,
maxDegreesPerSecond * Time.deltaTime
);
Bu targetRotation
, kare hızından bağımsız olarak tutarlı ve kontrol edilebilir bir hızda yaklaşmamızı sağlar - oyun mekaniğinin sonucunu / dürüstlüğünü etkileyen rotasyonlar için önemlidir (bir karakterin hareketini çevirmek veya oyuncu üzerinde bir taret girişi yapmak gibi). Doğal olarak, bu durumda Lerping / Slerping, hareketin yüksek kare hızlarında hızlanmasına neden olarak oyun dengesini etkileyebilir. (Bu yöntemlerin yanlış olduğunu söylemek değildir - adaleti değiştirmeden bunları doğru kullanmanın yolları vardır, sadece özen gerektirir. RotateTowards
Bu bizim için ilgilenen uygun bir kısayol sağlar)
n
farklı yönlerinizin (tutumlar, pozlar, vb.) Olduğunu söyleyin . Daha sonra, ağırlıkları kullanarak ortalamaları slerp / lerp'i genelleştirerek ortalayabilirsiniz. Bir kuaterniyonu, bir katı cisme belirli bir süre için açısal bir hız uygulamasına eşdeğer olan bir rotora dönüştürebilirsiniz. Dolayısıyla açısal hız entegrasyonunu kuaterniyonlarla da tanımlayabilirsiniz. İki yönelimin ne kadar farklı olduğunu da tahmin edebilirsiniz (hiperfer üzerindeki iki kuaterniyonun kapsadığı yayın uzunluğunu hesaplayın).