Menu
CoddyTech

Кватернионы

Часть раздела Физика и игровой процесс путешествия по Unity на Coddy. Урок 43 из 71.

Quaternion — это тип Unity для поворота: transform.rotation — это поворот, и значение, которое возвращает Quaternion.Euler, тоже. Его четыре числа x, y, z и w — не углы, и тебе никогда не нужно задавать их самостоятельно. Повороты перемножают. Поворот, умноженный на вектор, поворачивает этот вектор:

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);

Поворот ставится слева: Vector3.forward * transform.rotation не компилируется. В третьей строке смещение поворачивается согласно собственному повороту объекта, поэтому lamp — это точка на 1 единицу выше и на 2 единицы впереди объекта в его собственных направлениях, куда бы он ни был направлен.

Поворот, умноженный на другой поворот, объединяет эти два поворота. transform.rotation * Quaternion.Euler(0, 90, 0) — это поворот объекта, а затем поворот на четверть оборота вокруг его собственной оси y; если поменять порядок, поворот на четверть оборота будет вокруг оси y мира. Для вертикального объекта оба варианта дают одинаковый результат. Для самолёта, накренённого на 30 градусов, результат будет разным, потому что его собственная ось y наклоняется вместе с ним:

Quaternion banked = Quaternion.Euler(0, 0, 30);
Quaternion own = banked * Quaternion.Euler(0, 90, 0);    // нос (0.87, 0.5, 0): он набирает высоту во время поворота
Quaternion world = Quaternion.Euler(0, 90, 0) * banked;  // нос (1, 0, 0): он остаётся на одном уровне

Quaternion.identity — это отсутствие поворота, именно его ты передавал в Instantiate. Умножение на него ничего не меняет, а transform.rotation = Quaternion.identity; возвращает объект в исходное положение без поворота.

challenge icon

Задание

Средне

Сделай так, чтобы при нажатии Space вылетали три пули веером, поворачивающиеся вместе с пушкой.

  1. Замени строку Instantiate на for (int i = -1; i <= 1; i++).
  2. Внутри цикла задай Quaternion aim = transform.rotation * Quaternion.Euler(0, i * spread, 0);.
  3. Создавай каждую пулю на расстоянии 1 единицы по направлению её движения: Instantiate(bulletPrefab, transform.position + aim * Vector3.forward, aim);.

Нажми «Играть», поверни пушку и стреляй: три пули разлетятся веером с интервалом 20 градусов. Затем нажми «Проверить».

Попробуйте сами

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))
        {
            // Одна пуля летит прямо вперёд. Выпусти три пули под углами -spread, 0 и spread градусов.
            Instantiate(bulletPrefab, transform.position, transform.rotation);
        }
    }
}

Все уроки раздела Физика и игровой процесс

Потренируйтесь самостоятельно: Песочница Unity