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

TYSM I WORKED but that problem I had at the start still remains its not detecting the Slope or Angle here’s the script one more time:

Script Here

local function OnHoldingDown(Action)
print(Variables.Sprinting)
if Module.HoldDownEnabled then
if not Variables.Overheated and Variables.ActuallyEquipped and Variables.Enabled and Variables.Sprinting == true then

		local Slide = Instance.new("BodyVelocity")
		
		if Action == "Go"  and not HoldingDownCooldown then
			Character.Humanoid.WalkSpeed = 0
			ReplicatedStorage.Modules.ViewmodelHandler.Sliding.Value = true
			HoldingDownCooldown = true
			Variables.HoldDown = true
			
			--if Animations.HoldDownAnim then
			--	Animations.HoldDownAnim:Play(nil, nil, Module.HoldDownAnimationSpeed)
			--end
			--if VMAnimations.VMHoldDownAnim then
			--	VMAnimations.VMHoldDownAnim:Play(nil, nil, Module.VMHoldDownAnimationSpeed)
			--end
			Humanoid.HipHeight = 0.5
			Slide.MaxForce = Vector3.new(1,0,1) * 45000
			Slide.Velocity = Character.HumanoidRootPart.CFrame.lookVector * 50
			Slide.Parent = Character.HumanoidRootPart
			GlobalFunctionId = localFunctionId
			spawn(function()
				while wait(0.1) do
					if localFunctionId ~= GlobalFunctionId then
						Slide.Velocity = Slide.Velocity * 0
						if Slide then
							Slide:Destroy()
						end
						break
					end
					
					if Variables.Sprinting == true then
						local HumanoidRootPart = Character.PrimaryPart
						local HipHeight = Humanoid.HipHeight
						local Params = RaycastParams.new()
						Params.FilterDescendantsInstances = {Character}
						Params.FilterType = Enum.RaycastFilterType.Blacklist
						local ray = workspace:Raycast(HumanoidRootPart.Position, Vector3.new(0, -HipHeight - 1, 0), Params)
						local normal = ray and ray.Normal

						local incline = Vector3.new(1, 0, 0):Cross(Vector3.new(normal))

						if incline.magnitude == 0 then
							incline = Vector3.new(1, 0, 0)
						end

						local angle = math.acos(Vector3.new(0, 1, 0):Dot(incline))
						if angle > math.pi / 1.5 then
							print("Angle")
							Slide.Velocity = angle * Slide.Velocity * 1.1
						else
							print("No Angle")
							Slide.Velocity = Slide.Velocity * 0.9
						end
					else
						repeat wait(0.1) until Variables.Sprinting == true
					end
				end
			end)
		else
			GlobalFunctionId = os.clock()
			Character.Humanoid.WalkSpeed = 16
			Variables.HoldDown = false
			
			--if Animations.IdleAnim then
			--	Animations.IdleAnim:Play(nil, nil, Module.IdleAnimationSpeed)
			--end
			--if VMAnimations.VMIdleAnim then
			--	VMAnimations.VMIdleAnim:Play(nil, nil, Module.VMIdleAnimationSpeed)
			--end
			--if Animations.HoldDownAnim and Animations.HoldDownAnim.IsPlaying then
			--	Animations.HoldDownAnim:Stop()
			--end
			--if VMAnimations.VMHoldDownAnim and VMAnimations.VMHoldDownAnim.IsPlaying then
			--	VMAnimations.VMHoldDownAnim:Stop()
			--end
			Humanoid.HipHeight = 2
			Slide:Destroy()
			Character.PrimaryPart.Velocity = Vector3.new(0,0,0)
			ReplicatedStorage.Modules.ViewmodelHandler.Sliding.Value = false
			wait(0.5)
			HoldingDownCooldown = false
		end
	end
end

end

Bump since this post is very helpful, thanks for making it.

I am going to use dot for my game. The soldiers that you control move and turn via AlignForce/Orientation respectively, meaning its not instant turning so the unit can only shoot once it has lined up the shot. So i will use the dot product of the offset vector (offset vector from object a to b is always B.Position - A.Position) and the units LookVector to see if it is able to shoot

1 Like

Ok so there are just a couple things about this, number one:

if incline.magnitude == 0 then

This will literally never occur, instead it get down to like 0.005. Replace that with this:

if incline.magnitude < 0.01 then

Next, you may have meant to write this instead:

local incline = Vector3.new(0, 1, 0):Cross(Vector3.new(normal))

Vector3.new(1, 0, 0) is a vector pointing directly to the right, so I don’t think thats what you meant to put, however Vector3.new(0, 1, 0) faces directly up.

Hope all this helps man!

It seems to print the same thing still (“No Angle”) Although I feel I’m getting really close to getting it right
so here is my new script:

local function OnHoldingDown(Action)
	if Module.HoldDownEnabled then
		if not Variables.Overheated and Variables.ActuallyEquipped and Variables.Enabled then
			
			local Slide = Instance.new("BodyVelocity")
			
			if Action == "Go"  and not HoldingDownCooldown then
				Character.Humanoid.WalkSpeed = 0
				ReplicatedStorage.Modules.ViewmodelHandler.Sliding.Value = true
				HoldingDownCooldown = true
				Variables.HoldDown = true
				
				if Animations.HoldDownAnim then
					Animations.HoldDownAnim:Play(nil, nil, Module.HoldDownAnimationSpeed)
				end
				if VMAnimations.VMHoldDownAnim then
					VMAnimations.VMHoldDownAnim:Play(nil, nil, Module.VMHoldDownAnimationSpeed)
				end
				Humanoid.HipHeight = 0.5
				Slide.MaxForce = Vector3.new(1,0,1) * 45000
				Slide.Velocity = Character.HumanoidRootPart.CFrame.lookVector * 50
				Slide.Parent = Character.HumanoidRootPart
				GlobalFunctionId = localFunctionId
				spawn(function()
					while wait(0.1) do
						if localFunctionId ~= GlobalFunctionId then
							Slide.Velocity = Slide.Velocity * 0
							if Slide then
								Slide:Destroy()
							end
							break
						end
						
						--if Variables.Sprinting == true then
							local HumanoidRootPart = Character.PrimaryPart
							local HipHeight = Humanoid.HipHeight
							local Params = RaycastParams.new()
							Params.FilterDescendantsInstances = {Character}
							Params.FilterType = Enum.RaycastFilterType.Blacklist
							local ray = workspace:Raycast(HumanoidRootPart.Position, Vector3.new(0, -HipHeight - 1, 0), Params)
							local normal = ray and ray.Normal

							local incline = Vector3.new(0, 1, 0):Cross(Vector3.new(normal))

							if incline.magnitude < 0.01 then
								incline = Vector3.new(1, 0, 0)
							end

							local angle = math.acos(Vector3.new(0, 1, 0):Dot(incline))
							if angle > math.pi / 1.5 then
								print("Angle")
								Slide.Velocity = angle * Slide.Velocity * 1.1
							else
								print("No Angle")
								Slide.Velocity = Slide.Velocity * 0.9
							end
						--else
						--	repeat wait(0.1) until Variables.Sprinting == true
						--end
					end
				end)
			else
				GlobalFunctionId = os.clock()
				Character.Humanoid.WalkSpeed = 16
				Variables.HoldDown = false
				
				if Animations.IdleAnim then
					Animations.IdleAnim:Play(nil, nil, Module.IdleAnimationSpeed)
				end
				if VMAnimations.VMIdleAnim then
					VMAnimations.VMIdleAnim:Play(nil, nil, Module.VMIdleAnimationSpeed)
				end
				if Animations.HoldDownAnim and Animations.HoldDownAnim.IsPlaying then
					Animations.HoldDownAnim:Stop()
				end
				if VMAnimations.VMHoldDownAnim and VMAnimations.VMHoldDownAnim.IsPlaying then
					VMAnimations.VMHoldDownAnim:Stop()
				end
				Humanoid.HipHeight = 2
				Slide:Destroy()
				Character.PrimaryPart.Velocity = Vector3.new(0,0,0)
				ReplicatedStorage.Modules.ViewmodelHandler.Sliding.Value = false
				wait(0.5)
				HoldingDownCooldown = false
			end
		end
	end
end

Sorry if I’m late, but how exactly would you do this?

So basically, since you can use Dot to calculate how much your camera is looking at something:

First, find the unit vector between the monster’s position and your character’s position,

local unit = (monsterPosition - localCharacterPosition).Unit

This “unit” variable above is a Vector3 unit direction that the monster is from you.

You can calculate how much your camera is going in that direction by using:

local dotProduct = unit:Dot(camera.CFrame.LookVector)

The closer to -1 this “dotProduct” variable is, the farther away from the monster you are looking!

4 Likes

Thank you, this really helped!

1 Like

How can I implement this into my flying system to turn like a airplane?

I have the perfect solution NTAB:

What I would do is every RenderStep, calculate the Dot between: lastStepAirplaneLookVector and currentStepAirplaneLookVector.

(Excuse the unformatted code, I’m on my phone lol)

function renderStep()

    local currentStepAirplaneLookVector = plane.CFrame.LookVector

    local dot = lastStepAirplaneLookVector and lastStepAirplaneLookVector:Dot(currentStepAirplaneLookVector)

    lastStepAirplaneLookVector = currentStepAirplaneLookVector
end

Then, rotate the airplane by doing:

local rollAngle = (1 - dot) * rotateIntensity

However, this will roll the airplane in only one direction, regardless of which direction the airplane is turning.

We will need to add one more thing to make sure it rolls in the correct direction:

local _, currentY = currentStepAirplaneLookVector:ToEulerAnglesYXZ()
local _, lastY = lastStepAirplaneLookVector:ToEulerAnglesYXZ()

local rollDirection = math.sign(currentY - lastY)

Ok, we finally have everything we need!

function renderStep()

    local currentStepAirplaneLookVector = plane.CFrame.LookVector

    local dot = lastStepAirplaneLookVector and lastStepAirplaneLookVector:Dot(currentStepAirplaneLookVector) or 1

    local _, currentY = currentStepAirplaneLookVector:ToEulerAnglesYXZ()
    local _, lastY = lastStepAirplaneLookVector:ToEulerAnglesYXZ()

    local rollDirection = math.sign(currentY - lastY)

    local rollAngle = (1 - dot) * rotateIntensity * rollDirection

    lastStepAirplaneLookVector = currentStepAirplaneLookVector
end

You may have to do some adjusting of which angle to use, for example you may need to get difference of the X or Z angles instead of the Y angles, and you might need to multiply the rollDirection by -1 if the direction the plane rolls in is flipped - I’m only saying this cause I’m on my phone and haven’t tested any of this, but it should work :nerd_face:

1 Like

can this work on a character body?

1 Like

It will work on any model, just make sure to use the PrimaryPart or any specific part to get the model’s CFrame

1 Like

what is rotateIntensity and lastStepAirplaneLookVector what would i make those

1 Like

You should add Vector3:Angle() I didn’t even know it existed before today…

2 Likes

i think you should fix

Blockquote

CamLookVector:Dot(BlockLookVector)

Blockquote
i dont get it

Given a look vector how do I find the other basis of the space (right/upvector)

You need two vectors, it’s impossible to find the other two vectors with just one.

2 Likes

why not?, Isn’t that what they do in CFrame.lookat?

what I am trying to do is a climbing system and I want the Arm of an r5 Character point at an attachment placed in the climbing bar something like this:

I already have the points position on the climbing, But I am not sure how to rotate the arm correctly, also I can’t assume things like look vector = Vector3.new(0,1,0) because that’s not what I am trying to do.

Katrist is correct with this, there technically an infinite amount of possibilities for a RightVector and UpVector if only the LookVector is specified. That being said, for what your trying to do metatab1e, your going to want to get a Unit vector from the position of each arm to the position on the bar, then mess with the C0 value until it points in the right direction. A lot of the C0 stuff is just trial and error until it works lol

1 Like

I have no idea on how to randomly position the c0 using the direction vector and get a good result, every result I got is very ugly, also I get it there is an infinite possible values but for my purpose isn’t there a way to restrict the possible values?

Thanks for this, this is SUPER useful actually.

For fun I once wanted to brainstorm and figure out how I could possibly make a custom character mover/physics model and have the character rotate or change their local gravity when running up a wall for example.

But one issue I ran into was that rotating the character would be difficult without unintended side effects.

Ideally when a character’s direction of gravity and movement changes, you’d want them to be able to keep walking in a straight line while the gravity change happens.
What I was missing was figuring out on what axis or “imaginary beam” I’d have to rotate the character.

When a character runs up a wall, the floor is their old down vector, and the wall will be their new down vector.
And now I know I can just use cross product to smoothly rotate the character so they can keep running in a straight line relative to the camera/view.

2 Likes