Skip to main content
The Quaternion class represents a 3D rotation as four components — x, y, z, and w. Quaternions avoid the gimbal-lock problems of Euler angles and compose cleanly, making them the preferred way to describe rotations in RollingQuest scripts. You typically pair a Quaternion with a Vector3 to build a full transform: the Vector3 carries the position and the Quaternion carries the orientation. The most common constructors you’ll reach for are Quaternion.euler (when you think in degrees), Quaternion.angleAxis (when you want to spin around a specific axis), and Quaternion.lookRotation (when you need something to face a direction).

Constructors

-- Identity rotation (no rotation at all)
local rot = Quaternion.new()

-- Explicit raw components (x, y, z, w)
local raw = Quaternion.new(0, 0, 0, 1)

-- From Euler angles in degrees — the most readable form
local facing = Quaternion.euler(0, 90, 0)

-- Rotate 45 degrees around the Y axis
local spin = Quaternion.angleAxis(45, Vector3.up)

-- Face toward a target direction
local toward = Quaternion.lookRotation(Vector3.forward)
SignatureDescription
Quaternion.new()Returns the identity quaternion (0, 0, 0, 1).
Quaternion.new(x, y, z, w)Returns a quaternion with the given raw components.
Quaternion.euler(x, y, z)Builds a rotation from Euler angles (degrees) applied in Z→X→Y order.
Quaternion.euler(euler)Accepts a Vector3 of Euler angles in degrees.
Quaternion.angleAxis(angle, axis)Rotates angle degrees around the given axis vector.
Quaternion.lookRotation(forward)Rotates so the local forward aligns with forward.
Quaternion.lookRotation(forward, upwards)Same, but also constrains the local up direction.
Quaternion.fromToRotation(fromDirection, toDirection)Returns the shortest rotation that maps one direction to another.

Instance Properties

PropertyTypeRead-onlyDescription
xnumberNoThe X imaginary component.
ynumberNoThe Y imaginary component.
znumberNoThe Z imaginary component.
wnumberNoThe real component.
eulerAnglesVector3NoGet or set the rotation as Euler angles in degrees.
normalizedQuaternionYesA unit-length copy of the quaternion.
inverseQuaternionYesThe inverse (opposite) rotation.
You can also index a Quaternion by integer position (q[1] → x, q[2] → y, q[3] → z, q[4] → w) for read and write access.

Static Constants

ConstantDescription
Quaternion.identityThe identity rotation (0, 0, 0, 1) — represents no rotation.

Instance Methods

copy

Returns a new Quaternion with the same component values.
--- @return Quaternion
function Quaternion:copy()

set

Mutates the quaternion in place by assigning all four components.
--- @param x number
--- @param y number
--- @param z number
--- @param w number
function Quaternion:set(x, y, z, w)

normalize

Normalises the quaternion in place. To get a normalised copy without mutating the original, read the normalized property.
function Quaternion:normalize()

setLookRotation

Mutates the quaternion so the local forward faces view, optionally constraining the local up.
--- @param view Vector3
function Quaternion:setLookRotation(view)

--- @param view Vector3
--- @param up Vector3
function Quaternion:setLookRotation(view, up)

setFromToRotation

Mutates the quaternion to the shortest rotation from fromDirection to toDirection.
--- @param fromDirection Vector3
--- @param toDirection Vector3
function Quaternion:setFromToRotation(fromDirection, toDirection)

Static Methods

slerp

Spherically interpolates between two rotations by the clamped factor t.
--- @param a Quaternion
--- @param b Quaternion
--- @param t number
--- @return Quaternion
function Quaternion.slerp(a, b, t)

slerpUnclamped

Same as slerp but t is not clamped to [0, 1].
--- @param a Quaternion
--- @param b Quaternion
--- @param t number
--- @return Quaternion
function Quaternion.slerpUnclamped(a, b, t)

lerp

Linearly interpolates between two quaternions and normalises the result. Faster than slerp when the two rotations are close together.
--- @param a Quaternion
--- @param b Quaternion
--- @param t number
--- @return Quaternion
function Quaternion.lerp(a, b, t)

lerpUnclamped

Unclamped variant of lerp.
--- @param a Quaternion
--- @param b Quaternion
--- @param t number
--- @return Quaternion
function Quaternion.lerpUnclamped(a, b, t)

dot

Returns the dot product of two quaternions, which is useful for checking how similar two rotations are.
--- @param a Quaternion
--- @param b Quaternion
--- @return number
function Quaternion.dot(a, b)

angle

Returns the angle in degrees between two rotations.
--- @param a Quaternion
--- @param b Quaternion
--- @return number
function Quaternion.angle(a, b)

rotateTowards

Rotates from toward to by at most maxDegreesDelta degrees per call.
--- @param from Quaternion
--- @param to Quaternion
--- @param maxDegreesDelta number
--- @return Quaternion
function Quaternion.rotateTowards(from, to, maxDegreesDelta)

Usage Examples

Rotating a projectile direction

When you fire a projectile you often want it to travel in the direction the character is facing, possibly with an upward arc. Use Quaternion.euler to build the offset, then multiply it by a Vector3 representing the base forward direction.
-- The character faces along the Z axis
local baseForward = Vector3.forward

-- Add a 15-degree upward pitch to the shot
local launchRotation = Quaternion.euler(-15, 0, 0)

-- Apply the rotation to produce the launch direction
-- Quaternion * Vector3 is supported via the * operator
local launchDir = launchRotation * baseForward

-- Spawn the projectile and set its velocity
local proj = spawnProjectile()
proj.transform.rotation = launchRotation
proj.rigidbody.velocity  = Vector3.new(
    launchDir.x * 20,
    launchDir.y * 20,
    launchDir.z * 20
)

Smoothly turning to face the player

function OnUpdate(delta)
    local toPlayer = player.transform.position - self.transform.position
    local targetRot = Quaternion.lookRotation(toPlayer)
    self.transform.rotation = Quaternion.rotateTowards(
        self.transform.rotation,
        targetRot,
        90 * delta   -- 90 degrees per second
    )
end

Reading and writing Euler angles

-- Tilt the object 30 degrees on X
local rot = self.transform.rotation
local angles = rot.eulerAngles
angles.x = 30
rot.eulerAngles = angles
self.transform.rotation = rot

-- Or build it directly from Euler angles
self.transform.rotation = Quaternion.euler(30, 0, 0)
Vector3 and Quaternion are used together for transforms throughout RollingQuest. A Quaternion stores the orientation while a Vector3 stores the position. The * operator can apply a Quaternion rotation to a Vector3 direction.