Menu
CoddyTech

쿼터니언

Coddy Unity 여정의 물리와 게임플레이 섹션에 포함된 레슨. 71개 중 43번째.

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축을 중심으로 4분의 1바퀴 회전시킵니다. 순서를 바꾸면 4분의 1바퀴 회전은 월드의 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 플레이그라운드