Hayır, bu bir motor böceği veya belirli bir rotasyon gösteriminin bir eseri değildir (bunlar da olabilir, ancak bu etki rotasyonları, dahil edilen kuaterniyonları temsil eden her sistem için geçerlidir).
Rotasyonun üç boyutlu uzayda nasıl çalıştığı hakkında gerçek bir gerçeği keşfettiniz ve çeviri gibi diğer dönüşümler hakkındaki sezgilerimizden ayrılıyor:
Rotasyonları birden fazla eksende oluşturduğumuzda, elde ettiğimiz sonuç sadece her eksene uyguladığımız toplam / net değer değildir (çeviri için bekleyebileceğimiz gibi). Rotasyonları uyguladığımız sıra, her rotasyon bir sonraki rotasyonların uygulandığı eksenleri (nesnenin yerel eksenleri etrafında dönüyorsa) veya nesneyle eksen arasındaki ilişkiyi (dünya etrafında dönüyorsa) hareket ettirdikçe sonucu değiştirir eksen).
Zaman içinde eksen ilişkilerinin değişmesi, her eksenin ne yapması gerektiği konusunda sezgilerimizi karıştırır. Özellikle, bazı yalpa ve perde dönme kombinasyonları rulo dönmesi ile aynı sonucu verir!
Her basamağın talep ettiğimiz eksen üzerinde doğru döndüğünü doğrulayabilirsiniz - notasyonumuzda girişimizi engelleyen veya ikinci tahmin eden hiçbir motor arızası veya artefaktı yoktur - dönüşün küresel (veya hipersferik / kuaterniyon) dönüşü, dönüşümlerimiz anlamına gelir etrafında "birbirlerine". Küçük rotasyonlar için lokal olarak ortogonal olabilirler, fakat toplandıkça genel olarak ortogonal olmadıklarını görürüz.
Bu, yukarıdaki gibi 90 derecelik dönüşler için en çarpıcı ve net olanıdır, ancak dönen eksenler, soruda gösterildiği gibi birçok küçük dönüşte de sünmektedir.
Biz bu konuda ne yapacağız?
Zaten bir yalpalama rotasyon sisteminiz varsa, istenmeyen yuvarlanmayı ortadan kaldırmanın en hızlı yollarından biri, nesnenin yerel eksenleri yerine genel veya ana dönüşüm eksenlerinde çalışacak dönüşlerden birini değiştirmektir. Bu şekilde, iki - bir eksen arasındaki çapraz kontaminasyonu alamazsınız, kesinlikle kontrol altında kalır.
İşte yukarıdaki örnekte bir rulo haline gelen aynı pitch-yaw-pitch dizisi, ancak şimdi yaw'ımızı nesnenin yerine global Y ekseni etrafına uyguluyoruz.
Böylece birinci şahıs kamerayı "Pitch Locally, Yaw Globally" mantığıyla düzeltebiliriz:
void Update() {
float speed = lookSpeed * Time.deltaTime;
transform.Rotate(0f, Input.GetAxis("Horizontal") * speed, 0f, Space.World);
transform.Rotate(-Input.GetAxis("Vertical") * speed, 0f, 0f, Space.Self);
}
Rotasyonlarınızı çarpma kullanarak birleştiriyorsanız, aynı efekti elde etmek için çarpmalardan birinin sol / sağ sırasını çevirirsiniz:
// Yaw happens "over" the current rotation, in global coordinates.
Quaternion yaw = Quaternion.Euler(0f, Input.GetAxis("Horizontal") * speed, 0f);
transform.rotation = yaw * transform.rotation; // yaw on the left.
// Pitch happens "under" the current rotation, in local coordinates.
Quaternion pitch = Quaternion.Euler(-Input.GetAxis("Vertical") * speed, 0f, 0f);
transform.rotation = transform.rotation * pitch; // pitch on the right.
(Özel sipariş, ortamınızdaki çarpma kurallarına bağlı olacaktır, ancak left = daha genel / sağ = daha yerel, ortak bir seçimdir)
Bu, float değişkenleri olarak istediğiniz net toplam yalpa ve toplam perdeyi depolamakla eşdeğerdir, daha sonra her zaman bir kerede net sonucu uygulamak, sadece bu açılardan tek bir yeni oryantasyon kuaterniyonu veya matrisi oluşturmak (sadece totalPitch
kelepçeli kalmanız koşuluyla ):
// Construct a new orientation quaternion or matrix from Euler/Tait-Bryan angles.
var newRotation = Quaternion.Euler(totalPitch, totalYaw, 0f);
// Apply it to our object.
transform.rotation = newRotation;
Veya eşdeğer olarak...
// Form a view vector using total pitch & yaw as spherical coordinates.
Vector3 forward = new Vector3(
Mathf.cos(totalPitch) * Mathf.sin(totalYaw),
Mathf.sin(totalPitch),
Mathf.cos(totalPitch) * Mathf.cos(totalYaw));
// Construct an orientation or view matrix pointing in that direction.
var newRotation = Quaternion.LookRotation(forward, new Vector3(0, 1, 0));
// Apply it to our object.
transform.rotation = newRotation;
Bu küresel / yerel bölünmeyi kullanarak, dönüşlerin birbirlerini birleştirme ve etkileme şansları yoktur, çünkü bağımsız eksen kümelerine uygulanırlar.
Aynı fikir, dünyada döndürmek istediğimiz bir nesne ise yardımcı olabilir. Dünya gibi bir örnek için, genellikle onu ters çevirmek ve yawımızı yerel olarak uygulamak (böylece her zaman kutuplarının etrafında döner) ve global olarak adım atmak isteriz (böylece Avustralya’ya yönelmek / uzaklaşmak yerine bizim görüşümüze doğru / uzaklaşır) , işaret ettiği her yer ...)
Sınırlamalar
Bu küresel / yerel melez strateji her zaman doğru çözüm değildir. Örneğin, 3D uçuş / yüzme ile bir oyunda, düz yukarı / düz aşağı işaret ve hala tam kontrol sahibi olmak isteyebilirsiniz. Ancak bu ayar ile gimbal kilidini vuracaksınız - yalpalama ekseniniz (global yukarı) yuvarlanma ekseninize paralel (yerel ileri) ve bükülmeden sola veya sağa bakma şansınız yok.
Bunun gibi durumlarda bunun yerine yapabileceğiniz şey, yukarıdaki soruda başladığımız gibi saf yerel rotasyonları kullanmaktır (bu nedenle kontrolleriniz, nereye bakarsanız bakın aynı hissettirir), bu başlangıçta biraz yuvarlanmasına izin verir - ama sonra bunun için düzeltiriz.
Örneğin, "ileri" vektörümüzü güncellemek için yerel rotasyonları kullanabiliriz, daha sonra son oryantasyonumuzu oluşturmak için bu ileri vektörü bir referans "yukarı" vektörü ile birlikte kullanabiliriz. (Örneğin, Unity's Quaternion.LookRotation yöntemini kullanarak veya bu vektörlerden ortonormal bir matris el ile oluştururken) Yukarı vektörü kontrol ederek, rulo veya bükülmeyi kontrol ederiz.
Uçuş / yüzme örneğinde, bu düzeltmeleri zaman içinde kademeli olarak uygulamak isteyeceksiniz. Çok ani olursa, görüntü dikkat dağıtıcı bir şekilde durur. Bunun yerine, oyuncunun o andaki yukarı vektörünü kullanabilir ve görünümleri düzeye çıkana kadar dikey, kare kare yönlere doğru ipucu kullanabilirsiniz. Bunu bir dönüş sırasında uygulamak bazen oyuncunun kontrolleri boştayken kamerayı bükmekten daha az mide bulandırıcı olabilir.