Turret doesn't rotate properly

I have code to rotate a tank turret based on the mouse. But it dosnt exactly work. The turret rotates to the opposite of where the mouse is pointing:

Here is my code:

activateturret.Event:Connect(function(plr)
		self.turretconnection = RunService.Heartbeat:Connect(function()
			print("calculating")
			local mouse = game.ReplicatedStorage.mouses:FindFirstChild(plr.Name).Value
			local function getServoAngle(hinge, targetPosition)
				local baseAttachment = hinge.Attachment0

				local object_horizontal_offset = (baseAttachment.WorldCFrame):PointToObjectSpace(targetPosition)
				local object_yaw_angle = math.atan2(object_horizontal_offset.Y, -object_horizontal_offset.Z)
				object_yaw_angle = math.deg(object_yaw_angle)

				return object_yaw_angle
			end
			gun.Yaw.TargetAngle = getServoAngle(gun.Yaw, mouse.Position)
		end)
	end)

Here is my mouse updater:

Server:

local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")

local mousefolder = Instance.new("Folder")
mousefolder.Name = "mouses"
mousefolder.Parent = ReplicatedStorage

Players.PlayerAdded:Connect(function(player)
    local mouseindict = Instance.new("CFrameValue")
    mouseindict.Name = player.Name
    mouseindict.Parent = mousefolder
end)

local updatemouse:RemoteEvent = ReplicatedStorage.updatemouse

updatemouse.OnServerEvent:Connect(function(player,mouse)
    mousefolder:FindFirstChild(player.Name).Value = mouse
end)


Client:

local Players = game:GetService("Players")
print("Running")
local player = Players.LocalPlayer
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local RunService = game:GetService("RunService")
local mouse = player:GetMouse()
RunService.Heartbeat:Connect(function()
    ReplicatedStorage.updatemouse:FireServer(mouse.Hit)
    RunService.Heartbeat:Wait()
    task.wait()
end)

Thanks in advance!
6 Likes

Any Help? This is bothering me

1 Like

Perhaps you could upload a place file (.rbxl) with minimum stuff in it to reproduce the issue)? It’s hard to know what’s wrong without knowing how your HingeConstraint Attachments are oriented on the parts.

2 Likes

Your tank doesnt rotate properly because it doesnt account for the rotation of the part it is on

2 Likes

He’s transforming the world-space mouse.Hit point into the frame of reference of the tank turret’s base attachment, so it’s going to take into account how the tank is oriented in world. But that doesn’t mean that the rest of the math is right for the particular way these attachments are set up.

3 Likes

Why are you mixing the Y and the Z offset when calculating the Yaw rotation? I believe this is more fitting:

math.atan2(object_horizontal_offset.X, -object_horizontal_offset.Z)
1 Like

HingeConstraints rotate around their own x-axis, so a world point transformed into the frame of the hinge attachment would normally want to use the Y and Z values.

2 Likes

Maybe right, yeah. A bit unclear what rotation object_horizontal_offset has exactly.

2 Likes

In your code, object_horizontal_offset is the position in world where a ray from your mouse location would hit, transformed to be in the frame of that base attachment’s world CFrame. So object_horizontal_offset.Y is how far away the mouse hit point is from the tank attachment, in the direction of the attachment.WorldCFrame.UpVector. Likewise, object_horizontal_offset.Z is how far away it is in the direction of -attachment.WorldCFrame.LookVector (bit of Roblox weirdness here, LookVector in the negative Z direction, whereas X and Y are the RightVector and UpVector without a sign flip).

2 Likes

I suspect what you want is this:

math.atan2(object_horizontal_offset.Z, object_horizontal_offset.Y)

But this will probably only be what you expect if both hinge attachments have their yellow axis pointed up and their orange axis pointed towards the front of the tank.

2 Likes

Here is my place file:
tank.rbxm (198.8 KB)
whoops, frgot the module:
modules.rbxm (6.9 KB)

just require em and use the arguments for tank and gun

3 Likes

its still buggy, here is the script:

			local function getServoAngle(hinge, targetPosition)
				local baseAttachment = hinge.Attachment0

				local object_horizontal_offset = (baseAttachment.WorldCFrame):PointToObjectSpace(targetPosition)
				local object_yaw_angle = math.atan2(object_horizontal_offset.Z, object_horizontal_offset.Y)
				object_yaw_angle = math.deg(object_yaw_angle)

				return object_yaw_angle
			end
			gun.Yaw.TargetAngle = getServoAngle(gun.Yaw, mouse.Position)
2 Likes

I see you are updating the mouse position on the server and letting it work, a better and smoother way to do this is you set the Tank/Turret’s NetworkOwnership to the player. Then modify the tank on the client.

However, I also see that you are converting the mouse position in the world relative to the tank and using Y and Z, while you should be using Z and X instead.

Please check out these drawings to see the relation
(When converted to object space)

(What it looks like to be converted to object space)

Then you need to normalize the coordinate/direction (since you convert it to object space, you don't have to subtract 2 coordinates to get the direction, the coordinate is already the direction).

Then with the angle in radians, convert it to degrees and apply that to your HingeConstraint. But Roblox constraints aren’t always the best so if it doesn’t work it might be beneficial to try doing the same thing but without Roblox constraints and manipulate CFrame instead.

Edit: Fixed the first image correction of (X, Z) to atan2(Z, Y). It is supposed to be (X, Z) to atan2(Z, X)
Edit 2: Gave this more clarity and fixed some typos

2 Likes

so i use the formula provided to calculate the angle?

Also, i tried cframe manipulation, but it was very glitchy(the turret is on a tank, so it needs to be unanchored)

You haven’t normalized it yet, it should look something like this

local object_horizontal_offset = (baseAttachment.WorldCFrame):PointToObjectSpace(targetPosition).Unit
local object_yaw_angle = math.atan2(object_horizontal_offset.Z, object_horizontal_offset.X)
object_yaw_angle = math.deg(object_yaw_angle)

Edit: fixed math.deg(object_yaw_angle) to math.rad(object_yaw_angle)
Edit: changed it back

3 Likes

You are already using it, just in the wrong way so I gave you some information about the correct way of using it. The code I provided just now should already give you the angle, try printing it out every frame and see if it matches.

My bad, I forgot it doesn’t go well with welded objects.

3 Likes

i tried the normalized coordinate, but it basicly did the samething
Edit: printing the angle…

1 Like

Change this to

object_yaw_angle = math.rad(object_yaw_angle)

math.rad converts radians to degrees, while math.deg converts degrees to radians
math.rad converts degrees to radians, while math.deg converts radians to degrees`

2 Likes

errr now it just… dosnt rotate?
it just provides very small angles:
image

1 Like

Can you try printing it before converting it with math.rad? In the meantime I will try to make something replicating your tank turret.

1 Like