Vector3 Methods
by:
haotian2006Pre-requisites
Before reading this tutorial, you should know about vector3s. An explanation of vector3 exists in the Lua-Learning folder (not anymore). Or check out the Roblox docs.
Info
In this tutorial, I will teach you what each Vector3 method does and some of its use cases.
Dot(other: Vector3): Vector3
This method returns the scalar dot product between two vectors. The scalar dot formula is
scalarDot = (x1 * x2) + (y1 * y2) + (z1 * z2)
How is it useful?
Take this script for an example
local part1 = script.Parent.Part1 -- blue part
local part2 = script.Parent.Part2 -- green part
local dirArrow = script.Parent.Dir -- blue/yellow arrow
local function Update()
-- this will be visualized by the light blue/yellow arrow
local direction = (part2.Position - part1.Position).Unit
-- this will be visualized by the black arrow
local lv = part1.CFrame.lookVector
local dotProduct = direction:Dot(lv)
print("Dot: "..dotProduct)
if dotProduct > 0 then
-- if part 1 can see part 2
--turn blue
dirArrow.Color = Color3.new(0.0352941, 0.537255, 0.811765)
else
-- if part 1 cannot see part 2
--turn yellow
dirArrow.Color = Color3.new(1, 1, 0)
end
--makes the direction arrow point toward the direction
dirArrow.CFrame = CFrame.lookAt(part1.Position + Vector3.new(0,.5,0), part1.Position + Vector3.new(0, .5, 0) + direction)
end
Update()
part2.Changed:Connect(Update)
What this script does is if the green part is in a 180-degree view of the blue part, then make the arrow blue. Else make the arrow yellow, which you can see from the gif below. It also prints a value between -1 and 1 if you look at the output on the right side.
This can be very useful in some use cases, such as checking if you are in the field of view of an NPC.
But what if I want the NPC’s FOV to be narrower?
What you can do is replace this line
if dotProduct > 0 then
With
if dotProduct > math.cos(math.rad(MAX_ANGLE)) then
Why the math.cos you may ask?
Take this image as a reference
The bold black arrow is the lookVector. The blue arrows/rays create the cone shape, whereas the pink curve is the range in which the green part is considered inside, and the red line is the red part in the gif.
!!! info
A reminder to everyone that forgot trigonometry, cosine is the x value, and sine is the y value, but in this case, we only care about the x value, which is cosine.
Angle(other: Vector3, axis: Vector3 | nil ): number
This method returns the angle in radians between two vector3s. If an axis is provided, it will return an angle around the specified axis (default is Vector3.zAxis)
Example
(without providing axis)
local part1 = script.Parent.Part1 -- blue part
local part2 = script.Parent.Part2 -- green part
local dirArrow = script.Parent.Dir -- blue/yellow arrow
local function Update()
-- this will be visualized by the light blue/yellow arrow
local direction = (part2.Position - part1.Position).Unit
-- this will be visualized by the black arrow
local lv = part1.CFrame.lookVector
local Angle = direction:Angle(lv)
print("Angle: "..math.deg(Angle))
--makes the direction arrow point toward the direction
dirArrow.CFrame = CFrame.lookAt(part1.Position + Vector3.new(0, .5, 0), part1.Position + Vector3.new(0, .5, 0) + direction)
end
Update()
part2.Changed:Connect(Update)
(with axis argument = Vector3.xAxis)
!!! info
You can play around more in the test place that I will link at the bottom.
FuzzyEq(other: Vector3, epsilon: number): boolean
This method returns true if the given vector3 is within the current vector3 by the epsilon.
How it works
function fuzzyEq(a, b, epsilon)
return a == b or math.abs(a - b) <= (math.abs(a) + 1) * epsilon
end
function fuzzyEqVec(v1, v2, epsilon)
for _, axis in ipairs({"X", "Y", "Z"}) do
if not fuzzyEq(v1[axis], v2[axis], epsilon) then
return false
end
end
return true
end
Use cases
You can use it to detect when the player stopped moving using their MoveDirection
local humanoid: Humanoid = script.Parent.Humanoid
humanoid:GetPropertyChangedSignal("MoveDirection"):Connect(function()
--if it is close by .001
if humanoid.MoveDirection:FuzzyEq(Vector3.zero, .001) then
print("Player Stopped Moving")
end
end)
Cross(other: Vector3): Vector3
This method returns the cross product of the two vectors
Example
The blue arrow is the the direction(self), the yellow arrow is the cross(result), the black arrow is the lookVector(other)
local part1 = script.Parent.Part1 -- blue part
local part2 = script.Parent.Part2 -- green part
local dirArrow = script.Parent.Dir -- blue arrow
local crossArrow = script.Parent.Cross -- yellow arrow
local function Update()
-- this will be visualized by the light blue arrow
local direction = (part2.Position - part1.Position).Unit
-- this will be visualized by the black arrow
local lv = part1.CFrame.lookVector
local Cross = direction:Cross(lv)
print("Cross:", Cross)
--makes the direction arrow point toward the direction
dirArrow.CFrame = CFrame.lookAt(part1.Position + Vector3.new(0, .5, 0), part1.Position+Vector3.new(0, .5, 0) + direction)
crossArrow.CFrame = CFrame.lookAt(part1.Position + Vector3.new(0, .5, 0), part1.Position+Vector3.new(0, .5, 0) + Cross)
end
Update()
part2.Changed:Connect(Update)
Lerp(goal: Vector3, alpha: number): Vector3
This method returns a Vector3 that is interpolated to the goal by the alpha or percent.
How it works
function Lerp(start,goal,alpha)
return start + (goal - start) * alpha
end
function Vector3Lerp(start,goal,alpha)
return Vector3.new(
Lerp(start.X, goal.X, alpha),
Lerp(start.Y, goal.Y, alpha),
Lerp(start.Z, goal.Z, alpha),
)
end
???+ info
This also works and is more efficient then the other the way. Because Vector3 has **sub and **add metamethods
lua function Vector3Lerp(start,goal,alpha) return Lerp(start,goal,alpha) end
Use Case
You can use it to make parts move smoothly
local start = script.Parent.Part1 -- blue part
local end = script.Parent.Part2 -- green part
local move = script.Parent.Move -- grey part
while true do
-- lerp forward
for i = 0, 1, .01 do-- go from 0-1
task.wait()
Move.Position = Start.Position:Lerp(End.Position,i)
end
task.wait(2)
-- lerp back
for i = 0, 1, .01 do -- go from 0-1
task.wait()
Move.Position = End.Position:Lerp(Start.Position, i)
end
task.wait(2)
--repeat
end
(gif might be a bit laggy)
!!! Info “Difference between Lerp and TweenService” Tween service is a roblox Service that only works on Instances while with Lerping you don’t need instances and all you need is just two values.
Min(vector: Vector3): Vector3
This method returns a Vector3 with each component being the lowest value for both Vectors
local vector1 = Vector3.new(5,2,7)
local vector2 = Vector3.new(1,5,3)
print("Min: ", vector2:Min(vector1)) -- "Min: 1,2,3"
Max(vector: Vector3): Vector3
This method returns a Vector3 with each component as the highest for both Vectors
local vector1 = Vector3.new(5,2,7)
local vector2 = Vector3.new(1,5,3)
print("Max: ", vector2:Min(vector1)) -- "Max: 5,5,7"
Conclusion
I hope this helps you understand these methods better and what they do. The link to the example will be here. To view the code, simply make a copy of the game by pressing the 3 dots on the top right and clicking edit. Once you are in, you can move the green parts around to see different results. Anyways bye! (It is currently 4:18 AM, I spent 3 hours on this)