The Ultimate Guide to Vector3:Cross() and Vector3:Dot()

Hey there

After a lot of more inquisition about these topics, I have decided to make another tutorial!

This is going to be the simplest explanation ever made of Cross and Dot, so make sure you follow to the end :slightly_smiling_face:


By far, two of the most puzzling topics in scripting are Vector3:Cross() and Vector3:Dot(). However, after learning what they do, you will realize that they are actually 100x easier than using CFrames even!

You will also want to use them in your code when you realize what they can do, especially Dot()


Vector3:Dot()

Just to catch anyone up to speed, a LookVector is just the direction a CFrame is facing.

In this picture,

Block.CFrame.LookVector = Vector3.new(0, 1, 0)

Because it is facing directly up.


All Dot does is see how much 2 vectors go in the same direction.

If you are comparing how much in the same direction the LookVector of a Part and the LookVector of a Camera are going, it would look like this:

Here is what Dot will do for this:

local dotProduct = CamLookVector:Dot(BlockLookVector)
-- dotProduct = 1

Because the camera and the block are facing in the same direction, the Dot of their LookVectors will equal 1.


What if the Block and Camera were facing in opposite directions?

local dotProduct = CamLookVector:Dot(BlockLookVector)
-- dotProduct = -1

Because they are facing in opposite directions, the Dot of their LookVectors will equal -1.


What if they are facing at a right angle to each other?

local dotProduct = CamLookVector:Dot(BlockLookVector)
-- dotProduct = 0

Because they are facing at a right angle to each other, the Dot of their LookVectors will equal 0.


Also take note that It does not matter the order you use Dot() in:

CamLookVector:Dot(BlockLookVector)
BlockLookVector:Dot(CamLookVector)

Always equal the same thing.

CamLookVector:Dot(BlockLookVector) = BlockLookVector:Dot(CamLookVector)

Real Examples of Using Dot

  • You attacking an NPC only if your character is facing it

  • A monster that teleports behind you only if you are not looking at it

  • Finding the angle between two vectors
    angle (in radians) = math.acos(math.clamp(Vector1.Unit:Dot(Vector2.Unit), -1, 1))

  • Calculating how much an airplane is pointed forwards, perpendicular from the ground, in order to see how much drag in speed it should receive (If they are a perfect right angle, Dot will be 0)

That’s it for Dot!


Vector3:Cross()

If you skipped the explanation on Dot, make sure to go back and read it in order to understand what a LookVector is.


So since the LookVector is just the direction that a CFrame is facing, or Looking, the RightVector is the direction the right side of the CFrame is facing, and the UpVector is the direction the top side of the CFrame is facing.

Here is an example of what all three of them, the LookVector, RightVector, and UpVector look like on this rocket’s CFrame.

Don’t judge my rocket building skills :persevere:

In a new scenario, let’s say we have both the UpVector and the LookVector, but not the RightVector. We need to find it.

We can find the missing RightVector by using Cross.

All Cross does is find a vector that is perpendicular to the other two vectors that you give it.

In this scenario, because the RightVector is perpendicular to both the UpVector and LookVector, it will work perfectly!

local missingRightVector = LookVector:Cross(UpVector)

We found it! :sunglasses:


Now that we know that Cross will give us a vector a right angle from two other vectors, going back to that rocket picture:

We know that

local RightVector = LookVector:Cross(UpVector)

Cross is very useful for that case!


IMPORTANT:

LookVector:Cross(UpVector)
UpVector:Cross(LookVector)

Are not the same !!!

In order to find the RightVector, we have to use

LookVector:Cross(UpVector)

But if we wrongfully flipped it, it would give us the LeftVector, which we don’t want.


Taking a look at another case:

This time, we will use three random directions instead of the LookVector, UpVector, and RightVector.

Wait, where on Earth is the missing Vector C supposed to be now?!?!?

Since using Cross will give us a missing vector a right angle away from both Vector A and Vector B, it will say that Vector C is this:

If you don’t believe me, let’s check to see if this new Vector C is truly a right angle away from the other two vectors:

Yep! So there we have it, Vector C is a perpendicular to both Vector A and the Vector B!


That example used VectorB:Cross(VectorA) to find that VectorC, but if we wanted to get the other side from VectorC ( -VectorC ), we would do VectorA:Cross(VectorB)

(read what I said above a while ago about why the order of that matters)

Real Examples of Using Cross

  • Calculating the RightVector from any LookVector:Cross(UpVector)

  • Calculating the LookVector from any UpVector:Cross(RightVector)

  • Calculating the UpVector from any RightVector:Cross(LookVector)

  • Finding which axis to rotate a cannon to face a target

That’s it for Cross!


So that’s how to use Vector3:Dot() and Vector3:Cross()

Thanks everyone, and if you found this helpful be sure to leave a like and check out my other CFrame tutorials, especially if you want to learn more about these vectors I talked about in this tutorial.

Also, tell all of your scripter friends about this as so we can inform as many people as possible!


Cheers everyone,

– Moonvane

261 Likes

YES!! finnaly I understood what this things are actually doing!!

Vector hasn’t came in my studies yet but I now know most of things.
Apparently Roblox teaches us more than you think.

7 Likes

You can use this as a way to fight against silent aim.

Take the below code for example:

local function GetDirectionAccuracy(CF0,CF1)
	local Direction = (CF1.Position - CF0.Position).Unit
	local DotProduct = CF0.LookVector:Dot(Direction)
	return DotProduct
end

In this case, imagine CF0 is the CFrame of a user firing a bullet, and CF1 is the CFrame of the victim.

  • The closer the result is to 1, the more likely it was a legit shot.
  • The closer the result is to 0 or -1, then the more likely it was silent aim.

Great way to stop silent aim!

28 Likes

FInally somebody explains how :Cross() and :Dot() works, very good to know.

5 Likes

It’s a good guide.
can I translate this and post it on the Korean Forum?
I will attach the original link!

4 Likes

absolutely, I would be flattered!

4 Likes

Just wondering, but how would you use “:Cross()” to find that? :thinking:

1 Like

Ok so basically this is how it works:

local targetPosition = workspace.TankTarget.Position
local tankCenterPosition = tank.PrimaryPart.Position

local barrelLookVector = barrelTip.CFrame.LookVector
local unitToTarget = (targetPosition - tankCenterPosition).Unit

local whichAxisToTwistBarrelToFaceTarget = barrelLookVector:Cross(unitToTarget)

The whichAxisToTwistBarrelToFaceTarget is the axis in which you rotate the barrel.

When you do it like this, even when the tank is rotated on a hill, it will still know which axis for the barrel to twist around.

Btw this is probably the best video about Cross and Dot on the internet: (go to 8:40 for the tank problem explanation)

Hope this helps! :cowboy_hat_face:

4 Likes

How would you get lines going like this with :Cross() because I am assuming if you use cross on 2 of these, it would give you the vector you didn’t use. Example: VectorA:Cross(VectorB) would give Vector C and the other way around instead of a fourth line like the red one below.) I want to find a way to make a line going between the already existing vectors.

image

If this post doesn’t belong here, I would appreciate a DM telling me then I will gladly put it in scripting support.

1 Like

Yeah ofc, just use:

local vectorA = Vector3.new(0, 1, 0)
local vectorB = Vector3.new(0, 0, -1)
local yourVectorC = vectorA:Lerp(vectorB, 0.5).Unit * vectorA.Magnitude
print(yourVectorC)
1 Like

Finally, a good tutorial explaining :Cross() and :Dot(), really good guide :+1: (also your rocket building skills are 10x better than mine)

2 Likes

preciate that bro! :joy:

charactacter30

1 Like

I give you a whopping 1000/10 of your explanation

2 Likes

Uh @Moonvane , what if their angle are 45, will it be -0.5

1 Like

Yes it will be 0.5 if the angles are 45 from each other and -0.5 if the angles are 135 degrees from eachother (135 is just the flipped version of 45)

1 Like

I made a car, and I would like to detect next waypoints, the car moves by waypoints, if the next way point is to the right side of car, car should turn right

How do I detect if the waypoint is right side of the car

1 Like

Ok this actually doesn’t even need to use Dot, what you can do is just number the waypoints in order and then tween the car to the next waypoint.

1 Like

No like, the car moves through tween, but the thing is, the steering inside the car should also move like auto pilot, so I need to detect left or right the car moves in order to find which side its going

How do I do it?

1 Like

You can use dot product to find the angle, and cross product to find the direction left or right.

Ex from Sleitnick is AngleBetween signed:

local function AngleBetween(vectorA, vectorB)
	return math.acos(math.clamp(vectorA:Dot(vectorB), -1, 1))
end

local function AngleBetweenSigned(vectorA, vectorB, axis)
	local unsigned = AngleBetween(vectorA, vectorB)
	local cross = vectorA:Cross(vectorB)
	local sign = math.sign((axis.X * cross.X) + (axis.Y * cross.Y) + (axis.Z * cross.Z))
	return (unsigned * sign)
end
2 Likes

It does not work either it gets the correct angle

1 Like