Angle calculation inaccuracy issue when on a slope

I’m running into an issue where the Y for the turret’s gun is off when the vehicle is on an angle. I’m not quite sure why and i may be overlooking something from lack of sleep.

I’m calculating the angle via:
local BarDir = Pivot2.Part0.CFrame:pointToObjectSpace(mhit);

local y = math.atan2(BarDir.y,-BarDir.z)

where mhit is equiv. to mouse.hit.p and Pivot2 is a motor that has its C0 changed to aim up and down for the barrel.

Any help or suggestions would be appreciated, thanks in advance.


If I could take a guess, I would assume it has something to do with unfiltered parts in the mouse’s way (assuming you’re using the player’s mouse to determine the direction of the turret) with that being said, perhaps you could experiment with TargetFilter?

Apart from this, I have nothing useful to say. Sorry if this isn’t helpful :confused:

1 Like -flat surface with changes -angled surface with changes

Unfortunately it appears to not be the mouse itself but something else. Aside from target filters i’ve also used a alternative to mouse.hit which is getting the hit using mouse screen position and ScreenPointToRay() which also has the same results. Thanks for the suggestion though.

Sorry that this post may be a bit long, but I’ve been wanting to figure out how to do this for a while and here’s what I got!

First step is to get our turret working:

Looks great… if we were dealing in world space. This is using your method but without taking into account our base’s rotation. Lets approach this a different way.

Solving for Y


Blue = Y Axis Rotation
Red = X Axis Rotation
Green Node = Current Solution

As you can see, the blue plane aligns with the part constantly, while the red plane doesn’t really do that at all. Although that may be the case, we can infer from this that our problem just got simplified from 3D to 2D, so now we can just solve for the missing angle!

Finally we solve for X


Final Results

Hope this helps your problem! I’ve tested it with different base rotations and it’s been pretty accurate in my testing.


it seems to behave the same unless i’ve misinterpreted something.

local originCF = Gun.Part0.CFrame

local realPos = originCF*
local dir = realPos:pointToObjectSpace(mhit).Unit

local yAng = math.atan2(-dir.z,dir.x)

local currentSol = originCF**CFrame.Angles(0,yAng,0)
local localSpace = currentSol:pointToObjectSpace(mhit).Unit

local xAng = math.atan2(localSpace.Y, -localSpace.z)

Gun.C0 = * CFrame.fromEulerAnglesYXZ(0,yAng,0)

Turret = motor for the base rotation along x
Gun = motor for the y rotation of the barrel attached to turret
It is accurate like before on flat surfaces but the angled surface throws it off.

You’re using yAng in your second solution instead of xAng

Doesn’t seem to work. However i did strip the system down to just the turret for issue demonstration to possibly help and so you can see whats going on. The red is your solution that i implemented above and the green was my original. Sorry if this is eating up time.

I took a look at your Button1Down event function and saw you were not basing the target hit based on the turret’s CFrame. You’re doing something weird with WorldOrientation, which instead you could try doing something like

local cf = Veh.Gun.Barrel.Origin.WorldCFrame
local ray =,cf.lookVector*1200)

Oh thats a placeholder beam, basically i just rotate that attachment to modify the direction the beam fires, its set up just to shoot straight, it was just to see the pointing of the turret gun.



Is this the code you use in your real turrets? The barrel points true to where the mouse is for me so if it’s still working differently then idk how else to help.

Yes, the only it doesn’t aim true is when its on a slope.

It’s your beam’s code dude, which is what I was pointing out with my last reply. Even in your second picture you can see that the barrel is pointing to the mouse but the projection of the beam is different.

Here’s the updated code for your Button1Down event.

	local cf = Veh.Gun.Barrel.Origin.WorldCFrame
	local ray =,cf.RightVector*1200)
	local part, position = workspace:FindPartOnRayWithIgnoreList(ray, {game.Players.LocalPlayer.Character,Veh})
	local distance = (cf.p - position).magnitude
	local beam ="Part", workspace)

	beam.BrickColor ="Bright red")
	beam.Material = "Neon"
	beam.Transparency = 0.25
	beam.Anchored = true
	beam.Size =, 0.3, distance)
	beam.CFrame =  cf * CFrame.Angles(0,-math.pi*.5,0) *, 0, -distance / 2)

This makes me angry as that update shows that my original code was perfectly fine for aiming and i wasted a bunch of hours on trying to fix it, it was just the beam. Oh well, thank you for your time and effort, i appreciate it. i’ve learned a good lesson not to work on stuff when i’m half dead.

1 Like