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!
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.
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.
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.
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).
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.
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)
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)
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
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.
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`