local pos = player:position()
local above = pos + vec3(0, 2, 0)
local eye = player:eye_position()
local hit = world:raycast(eye, eye + player:velocity() * 20)vec3(x?, y?, z?) builds one, missing components default to 0. It is a plain table with
x, y, z fields you can read and write, and any table carrying numeric x/y/z works
where the API expects a vec3.
Arithmetic
+, -, * and / work componentwise against another vector, or uniformly against a
number (v * 2, 2 * v). Unary - negates, == compares components, tostring(v) prints
vec3(x, y, z). Every operation returns a new vector.
Methods
| Method | Returns |
|---|---|
v:length(), v:length_sq() |
Length; squared length is cheaper for comparisons |
v:distance(u), v:distance_sq(u) |
Distance to another vector, and its square |
v:normalized() |
Unit-length copy |
v:dot(u), v:cross(u) |
Dot and cross product |
v:lerp(u, t) |
Interpolation, t = 0 gives v and t = 1 gives u |
v:floor() |
Componentwise math.floor, so a block position |
v:copy() |
Independent copy |
v:unpack() |
Components as three return values |
local target = enemy:position():lerp(enemy:position() + enemy:velocity(), client.tick_delta())
rotation.look_at(target + vec3(0, enemy:height() / 2, 0))