Перейти к основному содержимому

Vector3

Трёхкомпонентный float-вектор. Используется везде где встречаются позиции, размеры, скорости и world-space направления (entity.Position, :GetBonePosition, game.CameraPosition, BasePart.Size и т.д.).

Статические функции12 (1 конструктор + 11 утилит)
Статические константы5 (zero, one, xAxis, yAxis, zAxis)
Поля instanceX, Y, Z, Magnitude, Unit
Методы instance11 (тот же набор что и static utilities, оба call-стиля поддерживаются)
Операторы+, -, *scalar, /scalar, унарный -

Алиасы. Большинство методов имеют две формы (PascalCase + lowercase): Vector3.Dot / Vector3.dot. Только new single-form. См. Обзор / Конвенция именования.

== это identity-only. Vector3.new(1,2,3) == Vector3.new(1,2,3) возвращает false. Метатаблица не реализует value-equality. Используй :FuzzyEq(other) для сравнения по значению. Pre-allocated singletons (Vector3.zero, .one, .xAxis, .yAxis, .zAxis) identity-equal к самим себе: Vector3.zero == Vector3.zero это true, но Vector3.zero == Vector3.new(0, 0, 0) это false, потому что new() всегда возвращает свежий userdata.

Краткий справочник

Static Vector3.*

ИмяСигнатураЗаметкаСтатус
new(x?, y?, z?) → Vector3конструктор от 0 до 3 чисел, missing args = 0проверено
zeroVector3 константа (0, 0, 0)identity для сложенияпроверено
oneVector3 константа (1, 1, 1)проверено
xAxisVector3 константа (1, 0, 0)проверено
yAxisVector3 константа (0, 1, 0)проверено
zAxisVector3 константа (0, 0, 1)проверено
Dot(a, b) → numberскалярное произведениепроверено
Cross(a, b) → Vector3правое векторное произведениепроверено
Lerp(a, b, t) → Vector3покомпонентная линейная интерполяцияпроверено
Floor(v) → Vector3покомпонентный math.floorпроверено
Ceil(v) → Vector3покомпонентный math.ceilпроверено
Abs(v) → Vector3покомпонентный math.absпроверено
Sign(v) → Vector3покомпонентный sign (-1, 0, +1)проверено
Min(a, b) → Vector3покомпонентный минимумпроверено
Max(a, b) → Vector3покомпонентный максимумпроверено
Angle(a, b) → numberбеззнаковый угол между векторами (радианы)проверено
FuzzyEq(a, b [, eps]) → boolepsilon-tolerant value-equalityпроверено

Instance v.* и v:*

ЧленТипЗаметка
v.X, v.Y, v.Znumberтри компоненты
v.Magnitudenumbersqrt(X*X + Y*Y + Z*Z), пересчитывается при каждом доступе
v.UnitVector3тот же вектор делённый на Magnitude (zero вектор даёт NaN-эквивалент, не обращайся к Unit на zero-векторе)
v:Dot(other), :Cross, :Lerp, :Floor, :Ceil, :Abs, :Sign, :Min, :Max, :Angle, :FuzzyEqразныеmethod-call форма, эквивалентна static с v как первый аргумент

new

Vector3.new(x?: number, y?: number, z?: number) → Vector3

Создаёт вектор. Missing args = 0. Проверенные return shapes:

ВызовРезультат
Vector3.new()(0, 0, 0)
Vector3.new(1)(1, 0, 0)
Vector3.new(1, 2)(1, 2, 0)
Vector3.new(1, 2, 3)(1, 2, 3)
Vector3.new(1, 2, 3, 4)(1, 2, 3) (extra args молча игнорируются)
Vector3.new(nil)(0, 0, 0) (nil = 0)
Vector3.new("s")error: "bad argument #1 to '?' (number expected, got string)"
local up    = Vector3.new(0, 1, 0)
local point = Vector3.new(120.5, 30, -88.2)
print(point.X, point.Y, point.Z, point.Magnitude)

Константы

Vector3.zero   → (0, 0, 0)
Vector3.one → (1, 1, 1)
Vector3.xAxis → (1, 0, 0)
Vector3.yAxis → (0, 1, 0)
Vector3.zAxis → (0, 0, 1)

Это pre-allocated immutable userdata. Используй их вместо создания свежего Vector3.new(0, 0, 0) в hot path.

local pos = entity.GetLocalPlayer().Position
if pos == Vector3.zero then

end
== это identity-only

Метатаблица не реализует value-equality. Vector3.new(1, 2, 3) == Vector3.new(1, 2, 3) возвращает false. Используй :FuzzyEq для сравнения по значению.


Операторы

OpПоведениеПроверено
a + bпокомпонентное сложение(1,2,3) + (4,5,6) = (5,7,9)
a - bпокомпонентное вычитание(1,2,3) - (4,5,6) = (-3,-3,-3)
a * kумножение на скаляр(1,2,3) * 2 = (2,4,6)
k * aумножение справа2 * (1,2,3) = (2,4,6)
a / kделение на скаляр(1,2,3) / 2 = (0.5, 1, 1.5)
-aунарный минус-(1,2,3) = (-1,-2,-3)
tostring(a)"%.6f, %.6f, %.6f"(1,2,3) → "1.000000, 2.000000, 3.000000"
Vector3 * Vector3 молча возвращает ноль

Vector3.new(1,2,3) * Vector3.new(4,5,6) возвращает (0, 0, 0), не покомпонентное произведение (4, 10, 18). Метаметод __mul не поддерживает vector-times-vector. Используй Vector3.Dot(a, b) для скалярного произведения или сделай покомпонентное умножение вручную:

local function v_mul(a, b) return Vector3.new(a.X*b.X, a.Y*b.Y, a.Z*b.Z) end

Dot

Vector3.Dot(a: Vector3, b: Vector3) → number
a:Dot(b) → number

Стандартное скалярное произведение a.X*b.X + a.Y*b.Y + a.Z*b.Z. Проверено: Vector3.new(1,2,3):Dot(Vector3.new(4,5,6)) возвращает 32.

local fwd  = (target_pos - my_pos).Unit
local face = camera_lookvec
local dot = fwd:Dot(face)
if dot > 0.95 then

Cross

Vector3.Cross(a: Vector3, b: Vector3) → Vector3
a:Cross(b) → Vector3

Правое векторное произведение. Проверено: Vector3.new(1,2,3):Cross(Vector3.new(4,5,6)) возвращает (-3, 6, -3).

local right = up:Cross(forward)

Lerp

Vector3.Lerp(a: Vector3, b: Vector3, t: number) → Vector3
a:Lerp(b, t) → Vector3

Линейная интерполяция a + (b - a) * t. t = 0 даёт a, t = 1 даёт b, без clamping для значений вне [0, 1].

Проверено: Vector3.new(1,2,3):Lerp(Vector3.new(4,5,6), 0.5) возвращает (2.5, 3.5, 4.5).

local mid = start_pos:Lerp(end_pos, 0.5)

Floor

Vector3.Floor(v: Vector3) → Vector3
v:Floor() → Vector3

Покомпонентный math.floor. Проверено: Vector3.new(-1.7, 2.3, -3.9):Floor() возвращает (-2, 2, -4).


Ceil

Vector3.Ceil(v: Vector3) → Vector3
v:Ceil() → Vector3

Покомпонентный math.ceil. Проверено: Vector3.new(-1.7, 2.3, -3.9):Ceil() возвращает (-1, 3, -3).


Abs

Vector3.Abs(v: Vector3) → Vector3
v:Abs() → Vector3

Покомпонентный math.abs. Проверено: Vector3.new(-1.7, 2.3, -3.9):Abs() возвращает (1.7, 2.3, 3.9).


Sign

Vector3.Sign(v: Vector3) → Vector3
v:Sign() → Vector3

Покомпонентный sign: возвращает -1, 0 или +1 для каждой оси. Проверено: Vector3.new(-1.7, 0, 3.9):Sign() возвращает (-1, 0, 1).


Min / Max

Vector3.Min(a: Vector3, b: Vector3) → Vector3
Vector3.Max(a: Vector3, b: Vector3) → Vector3
a:Min(b) / a:Max(b)

Покомпонентный минимум / максимум. Полезно для AABB clipping.

local lo = Vector3.Min(corner1, corner2)
local hi = Vector3.Max(corner1, corner2)
local size = hi - lo

Angle

Vector3.Angle(a: Vector3, b: Vector3) → number
a:Angle(b) → number

Возвращает беззнаковый угол в радианах между двумя векторами. Проверено: Vector3.xAxis:Angle(Vector3.yAxis) возвращает 1.5707963705063 (= π/2).

local angle_deg = math.deg(my_dir:Angle(target_dir))

FuzzyEq

Vector3.FuzzyEq(a: Vector3, b: Vector3 [, eps: number]) → bool
a:FuzzyEq(b)

Epsilon-tolerant value-equality. Используй вместо == (которое identity-only). Проверено: a:FuzzyEq(a) возвращает true.

if v:FuzzyEq(Vector3.zero) then

end

Паттерны

Расстояние между двумя world-точками

local function dist(a, b) return (a - b).Magnitude end

local me = entity.GetLocalPlayer():GetBonePosition("HumanoidRootPart")
for _, p in ipairs(entity.GetPlayers(true)) do
local their = p:GetBonePosition("HumanoidRootPart")
print(p.Name, dist(me, their))
end

Угол aim-направления к цели

local function angle_to(target_pos)
local cam = game.CameraPosition
local fwd = (game.GetService("Workspace").CurrentCamera and
game.GetService("Workspace").CurrentCamera.CFrame.LookVector)
or Vector3.zAxis
local to_tgt = (target_pos - cam).Unit
return fwd:Angle(to_tgt)
end

Snap позиции на 1-stud сетку

local function snap(v) return v:Floor() end

Покомпонентное умножение (оператор не работает)

local function v_scale(a, s) return Vector3.new(a.X*s.X, a.Y*s.Y, a.Z*s.Z) end

Проверка "сдвинулся ли игрок этот кадр"

local last_pos = Vector3.zero
cheat.register("onUpdate", function()
local pos = entity.GetLocalPlayer():GetBonePosition("HumanoidRootPart")
if not pos:FuzzyEq(last_pos) then

end
last_pos = pos
end)