Skip to content

vector

The vector library produces and operates on Luau’s native vector type — a first-class value (not a table) with x/y/z fields, no per-operation allocation, and SIMD-friendly speed. Engine position APIs will hand these back directly in a later phase.

Note the library is a table: build vectors with vector.create, not by calling vector(...).

vector.zero is (0, 0, 0); vector.one is (1, 1, 1).

print(vector.magnitude(vector.zero)) --> 0
print(vector.dot(vector.one, vector.one)) --> 3
local pos = vector.create(1, 2, 3)
print(pos.x, pos.y, pos.z) --> 1 2 3

The unit-length direction of v (a new vector).

local n = vector.normalize(vector.create(0, 0, 3))
print(n.z) --> 1

Length |v|.

print(vector.magnitude(vector.create(1, 2, 3))) --> 3.74165738677394
print(vector.magnitude(vector.create(0, 4, 3))) --> 5

Dot product — |a||b|cos θ; zero for perpendicular vectors.

print(vector.dot(vector.create(1, 2, 3), vector.create(4, 5, 6))) --> 32
print(vector.dot(vector.create(1, 0, 0), vector.create(0, 1, 0))) --> 0

Cross product — the vector perpendicular to both.

local n = vector.cross(vector.create(1, 0, 0), vector.create(0, 1, 0))
print(n.x, n.y, n.z) --> 0 0 1

The angle between two vectors, in radians.

print(vector.angle(vector.create(1, 0, 0), vector.create(0, 1, 0)))
--> 1.5707963267949 (pi/2)

All return new vectors; min/max pick per-component extremes — together they build axis-aligned bounds:

local a = vector.abs(vector.create(-1, 2, -3))
print(a.x, a.y, a.z) --> 1 2 3

Per-component math.sign: -1, 0, or 1 each.

local s = vector.sign(vector.create(-2.5, 0, 4))
print(s.x, s.y, s.z) --> -1 0 1

Per-component rounding.

local f = vector.floor(vector.create(1.7, -1.2, 0.5))
print(f.x, f.y, f.z) --> 1 -2 0

Per-component clamp.

local c = vector.clamp(vector.create(-1, 5, 2), vector.zero, vector.create(3, 3, 3))
print(c.x, c.y, c.z) --> 0 3 2
local lo = vector.min(vector.create(1, 5, 3), vector.create(4, 2, 0))
print(lo.x, lo.y, lo.z) --> 1 2 0
-- bounds around a moving point:
local center, radius = vector.create(10, 0, 10), 2
local mins = vector.min(
center - vector.create(radius, radius, radius),
center + vector.create(radius, radius, radius))

Component-wise linear interpolation (unclamped, like math.lerp).

local p = vector.lerp(vector.zero, vector.create(10, 20, 30), 0.5)
print(p.x, p.y, p.z) --> 5 10 15

Vectors support arithmetic and comparison directly:

local a, b = vector.create(1, 2, 3), vector.create(4, 5, 6)
print((a + b).x) --> 5 addition
print((a - b).x) --> -3 subtraction
print((a * 2).z) --> 6 scalar multiply
print((a / 2).z) --> 1.5 scalar divide
print(-a == vector.create(-1, -2, -3)) --> true
print(a.x, a.y, a.z) --> fields are readable