Finding the Target Angle between two vectors

I’m trying to find the desired angle to look at between two vectors.

AimMortarEvent.OnServerEvent:Connect(function(Player, Mortar, Hit)
	local Baseplate = Mortar:FindFirstChild("Baseplate")
	local Base = Mortar:FindFirstChild("Base")
	local Nozzle = Mortar:FindFirstChild("Nozzle", true)
	--local Tube = Base:FindFirstChild("Tube")
	
	local MaxElevation = 45
	local MinElevation = 15
	
	local dX = Hit.X - Nozzle.CFrame.X
	local dZ = Hit.Z - Nozzle.CFrame.Z
	
	local TargetAngle = math.atan2(dX, dZ)
	
	local TargetElevation = math.clamp(lerp(MaxElevation, MinElevation, (Hit.Position - Nozzle.Position).Magnitude / AimDistance), MinElevation, MaxElevation)
	local Hinge = Nozzle.Parent.Parent:FindFirstChild("Rotation")
	Hinge.TargetAngle = math.floor(math.deg(TargetAngle))
	
	
	local Elevation = Nozzle.Parent.Parent:FindFirstChild("Elevation")
	Elevation.TargetAngle = TargetElevation
	--print(TargetElevation)
	--print(math.deg(TargetAngle), Hinge.CurrentAngle)
end)

Hit is a CFrame, Mortar is a Model that contains the other parts in the code.

In this case I’m just looking for rotation, the elevation is fine.

Right now the problem is, I’m pretty sure I’m not telling it to look at a specific angle, I’m telling it to look at the angle that’s equivalent to the angle between the target and the nozzle. I’m sure there’s supposed to be some point where I find the difference between two angles and set the target angle to that. I’ve never did this before so I’m in unfamiliar grounds.

All help is welcome.

2 Likes

In a 2d plane consisting of x and z, z would become the opposite and x the adjacent. So you should do math.atan2(z, x) as atan2(a, b) would return a modified version of arctangent(a/b).

When I’m facing positive X it behaves correctly but if I’m facing negative x it goes wonky.

Positive:

Negative:

I might have something that could work. I had to go back and refresh myself on a calculus equation that given two vectors, calculates the angle between the vectors. Here it is:

a=vector1
b=vector2

(a * b)/(|a| * |b|)=cos(theta)

Note that a*b is the dot product of vectors a and b. Also note that |a| is the magnitude of vector a.

Here’s an example:

a=<1,1>
b=<0,1>

plugging this into our equation and solving gives us:

1/sqr(2) = cos(theta)

cos^-1(1/(sqr(2)))=theta

this gives us theta = 45 degrees.

Does it eventually reach the desired angle? For the negative one.

Nope it doesn’t reach the desired angle at all.

:eyes: :eyes: :thinking: :eyes:

You lost me at a=vector1 lol.

I barely understand the math I currently have. all I know is that to find the angle between two vectors you would use math.atan2 . I believe your approach steps me through the process of what that’s doing. But could you simplify it for me?

1 Like

No problem. But could you tell me what variables in your code are your two vectors.

Hit is a CFrame, which is basically the target location I can get the vector from that.

And the other vector is a part so I can choose the best part that would give me an angle and use that.

Nozzle is a small part on the end of the barrel basically where the projectile spawns. There’s also a Baseplate that doesn’t move, a base that does rotate, and the tube. The nozzle, tube, and base is all attached and is what rotates towards the “Hit” position.

I’m not really sure which to use for the best result in this case.

I’m having a hard time understanding where all these variables come in and what your trying to calculate. It seems like you want players to only be able to build on their base. But could you draw an illustration on one of your screen shots telling me where these variables come in and where the angle is. :slightly_smiling_face:

Update: Oh, I just realized your trying to fire a Mortar.

Here we go. It’s a Mortar.

Oh ok. Things are making much more sense. Where is the second line for that angle?

image

that would probably be based on the direction of the baseplate.

What baseplate? Is this the water or what your avatar is standing on?

image

The yellow part is the baseplate. The only part on the mortar that doesn’t rotate. Sorry

Oh got it.

So this is the angle you want? Could I ask what you use this angle for? Is this to rotate the mortar? What variables hold the direction of the mortar’s base and the direction of the mortar to the target?
image

Yeah the tube part of the mortar that’s connected to the baseplate is what’s rotating towards the said angle / target. There are no variables for those at the moment. I’m using a Hinge btw.

Alright. It seems like our A vector would be baseplate.lookvector? Could also be baseplate.CFrame.rightvector or baseplate.CFrame.upvector. It could also be negative of any one of those. You will probably have to play around to figure out which one you need. Vector B would be (Target.Position-baseplate.Position).Unit. I don’t think you need to do this but seeing that you don’t use the y axis at all, I would set vector A = Vector2.new(A.X,A.Z) and vector B = Vector2.new(B.X,B.Z). Both target’s position and baseplate’s position has the same y value right? Or you modify it so you don’t have to deal with the y axis?

They probably won’t but the projectile is a parabola and travels towards the path regardless of rotation. So rotation here is just for the visual effect.

Also the baseplate is negative LookVector if that helps. I know you might be asking yourself how the heck I pulled off a parabola… I’m asking myself the same question.

1 Like

lol. Just to make sure, the target part is always forced at the same y as baseplate right?