Phép nhân
Ít nhất là về mặt thực thi Đệ tứ của Unity, thứ tự nhân được mô tả trong câu hỏi là không chính xác. Điều này rất quan trọng vì xoay 3D không giao hoán .
Vì vậy, nếu tôi muốn xoay một đối tượng bằng cách rotationChange
bắt đầu từ nó, currentOrientation
tôi sẽ viết nó như thế này:
Quaternion newOrientation = rotationChange * currentOrientation;
(ví dụ: Các phép biến đổi xếp chồng lên nhau sang trái - giống như quy ước ma trận của Unity. Xoay vòng ngoài cùng bên phải được áp dụng trước / ở đầu "cục bộ nhất")
Và nếu tôi muốn chuyển đổi một hướng hoặc vectơ bù bằng một phép quay, tôi sẽ viết nó như sau:
Vector3 rotatedOffsetVector = rotationChange * currentOffsetVector;
(Unity sẽ tạo ra một lỗi biên dịch nếu bạn làm ngược lại)
Pha trộn
Đối với hầu hết các trường hợp, bạn có thể thoát khỏi vòng quay Lerping. Đó là bởi vì góc được sử dụng "dưới mui xe" trong một phần tư là một nửa góc quay, làm cho nó gần với phép tính gần đúng tuyến tính của Lerp hơn là một Ma trận (nói chung sẽ không Lerp tốt!). Kiểm tra khoảng 40 phút vào video này để giải thích thêm .
Một trường hợp khi bạn thực sự cần Slerp là khi bạn cần tốc độ phù hợp theo thời gian, như nội suy giữa các khung hình chính trên dòng thời gian hoạt hình. Đối với các trường hợp bạn chỉ quan tâm rằng một đầu ra là trung gian giữa hai đầu vào (như pha trộn các lớp của một hình ảnh động) thì thường Lerp phục vụ khá tốt.
Khác gì?
Các dấu chấm sản phẩm của hai quaternion đơn vị cung cấp cho các cosin của góc giữa chúng, vì vậy bạn có thể sử dụng các sản phẩm chấm như một biện pháp tương tự nếu bạn cần phải so sánh quay. Tuy nhiên, điều này hơi khó hiểu, vì vậy, đối với mã dễ đọc hơn, tôi thường sử dụng Qu Parention.Angle (a, b) , điều này thể hiện rõ hơn rằng chúng ta đang so sánh các góc, theo các đơn vị (độ) quen thuộc.
Những loại phương thức tiện lợi mà Unity cung cấp cho Quancyions là siêu hữu ích. Trong hầu hết mọi dự án tôi đều sử dụng cái này ít nhất một vài lần :
Quaternion.LookRotation(Vector3 forward, Vector3 up)
Điều này xây dựng một tứ phương rằng:
- xoay trục z + cục bộ thành điểm chính xác dọc theo
forward
đối số vectơ
- xoay trục y + cục bộ thành điểm càng gần càng tốt với
up
đối số vectơ, nếu được cung cấp hoặc (0, 1, 0)
nếu bị bỏ qua
Lý do "lên" chỉ nhận được "càng gần càng tốt" là hệ thống bị quá hạn. Đối mặt với z + để forward
sử dụng tối đa hai bậc tự do (ví dụ: ngáp và cao độ) để chúng ta chỉ còn một bậc tự do (cuộn).
Tôi thấy khá thường xuyên tôi muốn một cái gì đó với các thuộc tính chính xác ngược lại: Tôi muốn cục bộ y + chỉ chính xác up
và z + cục bộ càng gần càng tốt forward
với sự tự do còn lại.
Ví dụ, điều này xuất hiện khi cố gắng tạo khung tọa độ tương đối máy ảnh cho đầu vào chuyển động: Tôi muốn hướng lên cục bộ của mình vuông góc với mặt sàn hoặc bề mặt nghiêng bình thường, vì vậy đầu vào của tôi không cố gắng đưa nhân vật vào địa hình hoặc đẩy họ ra khỏi nó.
Bạn cũng có thể nhận được điều này nếu bạn muốn vỏ tháp pháo của xe tăng đối mặt với mục tiêu, mà không bị bong ra khỏi thân xe tăng khi nhắm lên / xuống.
Chúng ta có thể xây dựng chức năng tiện lợi của riêng mình để thực hiện việc này, sử dụng LookRotation
cho việc nâng vật nặng:
Quaternion TurretLookRotation(Vector3 approximateForward, Vector3 exactUp)
{
Quaternion rotateZToUp = Quaternion.LookRotation(exactUp, -approximateForward);
Quaternion rotateYToZ = Quaternion.Euler(90f, 0f, 0f);
return rotateZToUp * rotateYToZ;
}
Ở đây trước tiên chúng ta xoay cục bộ y + sang z + và z + cục bộ sang y-.
Sau đó, chúng tôi xoay z + mới theo hướng lên của chúng tôi (vì vậy kết quả thực là các điểm y + cục bộ trực tiếp dọc theo exactUp
) và y + mới càng gần càng tốt với hướng chuyển tiếp bị phủ định (vì vậy kết quả thực là các điểm z + cục bộ càng gần càng tốt approximateForward
)
Một phương pháp tiện lợi tiện dụng khác là Quaternion.RotateTowards
, mà tôi thường sử dụng như vậy:
Quaternion newRotation = Quaternion.RotateTowards(
oldRotation,
targetRotation,
maxDegreesPerSecond * Time.deltaTime
);
Điều này cho phép chúng tôi tiếp cận targetRotation
với tốc độ ổn định, có thể kiểm soát được bất kể tốc độ khung hình - quan trọng đối với các phép quay ảnh hưởng đến kết quả / sự công bằng của cơ chế chơi trò chơi (như chuyển động của nhân vật hoặc theo dõi tháp pháo trên người chơi). Naively Lerping / Slerping trong tình huống này có thể dễ dàng dẫn đến các trường hợp chuyển động trở nên nhanh hơn ở tốc độ khung hình cao, ảnh hưởng đến cân bằng trò chơi. (Điều đó không có nghĩa là các phương pháp này sai - có nhiều cách để sử dụng chúng một cách chính xác mà không thay đổi sự công bằng, nó chỉ cần sự chăm sóc. RotateTowards
Cung cấp một lối tắt thuận tiện giúp xử lý vấn đề này cho chúng tôi)
n
các định hướng khác nhau (thái độ, tư thế, v.v.). Sau đó, bạn có thể trung bình chúng bằng cách sử dụng trọng số, khái quát hóa hiệu quả slerp / lerp. Bạn cũng có thể chuyển đổi một bậc bốn thành một rôto, tương đương với việc áp dụng vận tốc góc trong một khoảng thời gian nhất định cho một cơ thể cứng nhắc. Do đó, bạn có thể mô tả tích hợp vận tốc góc với tứ phương. Bạn cũng có thể ước tính mức độ khác nhau của hai hướng (tính chiều dài của cung tròn được kéo dài bởi hai bậc bốn trên siêu cầu).