Menu
CoddyTech

Quaternion

Thuộc phần Vật lý và lối chơi trong hành trình Unity của Coddy. Bài học 43 trên 71.

Quaternion là kiểu dữ liệu biểu diễn phép xoay trong Unity: transform.rotation là một giá trị thuộc kiểu này, và giá trị mà Quaternion.Euler trả về cũng vậy. Bốn số x, y, z và w của nó không phải là góc, và bạn không cần tự đặt chúng. Khi làm việc với phép xoay, bạn sẽ nhân chúng. Phép xoay nhân với một vectơ sẽ xoay vectơ đó:

Vector3 a = Quaternion.Euler(0, 90, 0) * Vector3.forward;       // (1, 0, 0)
Vector3 b = Quaternion.Euler(0, 0, 45) * new Vector3(2, 0, 0);  // (1.41, 1.41, 0)
Vector3 lamp = transform.position + transform.rotation * new Vector3(0, 1, 2);

Phép xoay phải nằm bên trái: Vector3.forward * transform.rotation sẽ không biên dịch. Dòng thứ ba xoay một độ lệch theo phép xoay riêng của đối tượng, vì vậy lamp là điểm nằm cao hơn đối tượng 1 đơn vị và ở phía trước 2 đơn vị theo các hướng riêng của nó, bất kể nó quay mặt về hướng nào.

Phép xoay nhân với một phép xoay sẽ kết hợp hai lần xoay. transform.rotation * Quaternion.Euler(0, 90, 0) áp dụng phép xoay của đối tượng, rồi xoay một phần tư vòng quanh trục y riêng của nó; nếu đổi thứ tự, phép xoay một phần tư vòng sẽ quanh trục y của thế giới. Với một đối tượng đứng thẳng, cả hai đều cho cùng một kết quả. Với một chiếc máy bay nghiêng 30 độ, chúng cho kết quả khác nhau vì trục y riêng của nó cũng nghiêng theo:

Quaternion banked = Quaternion.Euler(0, 0, 30);
Quaternion own = banked * Quaternion.Euler(0, 90, 0);    // đầu mũi (0.87, 0.5, 0): nó hướng lên khi rẽ
Quaternion world = Quaternion.Euler(0, 90, 0) * banked;  // đầu mũi (1, 0, 0): nó giữ nguyên độ cao

Quaternion.identity biểu thị không xoay chút nào, chính là giá trị bạn đã truyền cho Instantiate. Nhân với giá trị này không làm thay đổi gì, còn transform.rotation = Quaternion.identity; đưa đối tượng về tư thế chưa xoay.

challenge icon

Thử thách

Trung bình

Thiết lập phím Space để bắn ra một loạt ba viên đạn xoay theo khẩu súng.

  1. Thay dòng Instantiate bằng for (int i = -1; i <= 1; i++).
  2. Trong vòng lặp, đặt Quaternion aim = transform.rotation * Quaternion.Euler(0, i * spread, 0);.
  3. Tạo mỗi viên đạn cách 1 đơn vị theo hướng của nó: Instantiate(bulletPrefab, transform.position + aim * Vector3.forward, aim);.

Nhấn Chơi, xoay và bắn: ba viên đạn xòe ra, cách nhau 20 độ. Sau đó nhấn Kiểm tra.

Tự làm thử

using UnityEngine;

public class Gun : MonoBehaviour
{
    public GameObject bulletPrefab;
    public float turnSpeed = 90f;
    public float spread = 20f;

    void Update()
    {
        if (Input.GetKey(KeyCode.RightArrow)) transform.Rotate(0, turnSpeed * Time.deltaTime, 0);
        if (Input.GetKey(KeyCode.LeftArrow)) transform.Rotate(0, -turnSpeed * Time.deltaTime, 0);

        if (Input.GetKeyDown(KeyCode.Space))
        {
            // Một viên đạn bay thẳng về phía trước. Bắn ba viên theo các góc -spread, 0 và spread độ.
            Instantiate(bulletPrefab, transform.position, transform.rotation);
        }
    }
}

Tất cả bài học trong Vật lý và lối chơi

Tự luyện tập: Playground Unity