Appearance
vec
A point in space, or a direction. vec is the maths helper every position, rotation and direction in this API is made of.
luau
local vec = require("vec")Making one
luau
vec() -- (0, 0, 0)
vec(5) -- (5, 5, 5) — the same on every axis
vec(1, 2, 3) -- per axis
vec({ x = 1, y = 2, z = 3 }) -- a copy of any table with x, y, z
vec(self:position()) -- a copy of another vecYou rarely need to build one. Every reading in this API already hands you a vec — self:position(), self:rotation(), hit.pos, hit.normal, shot.eye, shot.dir, player.pos, player.look. And every verb that takes a point also accepts a plain { x =, y =, z = } table. vec is what you reach for when you want to do maths on one.
Maths on points
luau
local a = vec(1, 0, 0)
local b = vec(0, 2, 0)
a + b -- vec(1, 2, 0)
a - b -- vec(1, -2, 0)
-a -- vec(-1, 0, 0)
a * 3 -- vec(3, 0, 0) — scaling
3 * a -- the same
a / 2 -- vec(0.5, 0, 0)
a == b -- false
tostring(a) -- "vec(1, 0, 0)"Two you will use constantly:
luau
-- a step of 2 metres in the direction somebody is looking
local ahead = player.pos + player.look * 2
-- just off a surface, so a decal does not flicker against it
local safe = hit.pos + hit.normal * 0.006Methods
len
v:len() → number
How long the vector is. On a direction it is 1; on the difference between two points it is the distance between them.
dist
v:dist(other) → number
Distance between two points. Clearer than (a - b):len() and does the same thing.
luau
if self:position():dist(player.pos) > 20 then
return -- too far away to care
endnormalize
v:normalize() → vec
The same direction, one metre long. This is what turns "the way from me to you" into something you can multiply by a speed.
luau
local away = (target - here):normalize()
self:set_velocity(away * 12)A zero-length vector normalizes to zero rather than to an error or a broken number, so you never have to guard against it.
dot
v:dot(other) → number
How much two directions agree. 1 is the same way, 0 is a right angle, -1 is opposite.
The practical use is a field of view — "is this in front of me?":
luau
local to_player = (player.pos - here):normalize()
if facing:dot(to_player) > 0.7 then
-- roughly within a 45° cone in front
endcross
v:cross(other) → vec
A direction at right angles to both. Mostly used to find "sideways" from "forward" and "up".
luau
local right = forward:cross(vec(0, 1, 0)):normalize()lerp
v:lerp(other, t) → vec
A point part-way between two. t = 0 is where you started, t = 1 is the target, 0.5 is halfway.
luau
-- creep a tenth of the way toward the target each tick
self:move_to(here:lerp(target, 0.1))unpack
v:unpack() → three numbers
luau
local x, y, z = here:unpack()Notes
A vec never changes. Every operation returns a new one, so handing yours to something else can never come back modified.
It costs nothing. vec is pure arithmetic inside your script — it never touches the world, never counts against your effect budget, and never needs a permission. Misusing it (multiplying two vecs, say) is an ordinary script error, like any other bug.
See also
- self — where readings come from
- world:raycast —
posandnormal
