Quaternions
Part of the Physics and Gameplay section of Coddy's Unity journey. Lesson 43 of 71.
A Quaternion is Unity's type for a rotation: transform.rotation is one, and so is what Quaternion.Euler returns. Its four numbers x, y, z and w are not angles, and you never need to set them yourself. What you do with rotations is multiply. A rotation times a vector turns the vector:
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);The rotation goes on the left: Vector3.forward * transform.rotation does not compile. The third line turns an offset by the object's own rotation, so lamp is the point 1 unit above and 2 in front of the object in its own directions, whichever way it faces.
A rotation times a rotation combines the two turns. transform.rotation * Quaternion.Euler(0, 90, 0) is the object's rotation followed by a quarter turn around its own y axis; with the order swapped, the quarter turn is around the world's y axis. For an upright object both give the same result. For a plane banked 30 degrees they do not, because its own y axis leans with it:
Quaternion banked = Quaternion.Euler(0, 0, 30);
Quaternion own = banked * Quaternion.Euler(0, 90, 0); // nose (0.87, 0.5, 0): it climbs as it turns
Quaternion world = Quaternion.Euler(0, 90, 0) * banked; // nose (1, 0, 0): it stays levelQuaternion.identity is no turn at all, the one you have passed to Instantiate. Multiplying by it changes nothing, and transform.rotation = Quaternion.identity; puts an object back to its unturned pose.
Challenge
MediumMake Space fire a spread of three bullets that turns with the gun.
- Replace the
Instantiateline withfor (int i = -1; i <= 1; i++). - In it, set
Quaternion aim = transform.rotation * Quaternion.Euler(0, i * spread, 0);. - Spawn each bullet 1 unit out along its direction:
Instantiate(bulletPrefab, transform.position + aim * Vector3.forward, aim);.
Press Play, turn and fire: three bullets fan out, 20 degrees apart. Then Check.
Try it yourself
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))
{
// One bullet, straight ahead. Fire three: -spread, 0 and spread degrees.
Instantiate(bulletPrefab, transform.position, transform.rotation);
}
}
}
All lessons in Physics and Gameplay
1Rigidbody
Gravity and MassPush with AddForceJump with an ImpulseFixedUpdate for PhysicsVelocityKinematic BodiesRecap: Launch Pad4Coroutines
InvokeInvokeRepeating, CancelInvokeYour First CoroutineLoops in CoroutinesStopping CoroutinesRecap: Countdown10Project: Arena Escape
The ArenaHunters2Collisions
OnCollisionEnterWhat Did I Hit?Break on ImpactStanding on the GroundBounce and FrictionCollider ShapesRecap: Breakable WallPractice on your own: Unity playground