Trying to make constant speed rotating tank turret

I want to try and create a tank turret that follows your mouse, but at a constant rotation speed (not using lerp). I want to know if there is maybe a function that roblox has that I can use, or if not, a general idea of how I would do this. A good example of this would be this military tycoon tank that I saw. I tried looking for solutions, but I couldn’t find any.

If you use a Servo HingeConstraint then it’s trivial, just set TargetAngle.

If you use a Motor6D or some other manual way of setting the CFrame of the turret relative to the tank, then you can use a function like this instead of lerp:

function rotateCFrameTowards(current: CFrame, target: CFrame, radians: number): 
    assert(radians >= 0)
    local fullTransform = current:ToObjectSpace(target)
    local axis, fullRadians = transform:ToAxisAngle()
    local clampedRadians = math.min(fullRadians, radians)
    local clampedTransform = CFrame.fromAxisAngle(axis, clampedRadians)
    return current * clampedTransform
end

… at least I think that should work, I can’t test it right now. You just call it like this:

local TURN_SPEED_IN_RADIANS_PER_SECOND = math.rad(45)
local targetC1 = --whatever you want
function onStepped(dt)
    turretJoint.C1 = rotateCFrameTowards(turretJoint.C1, targetC1, dt * TURN_SPEED_IN_RADIANS_PER_SECOND)
end

I can see how the servo motor would work, but how would I get the rotation angle from the mouse for the x rotation and y rotation separately?

There’s quite a few threads about that already, try searching around

Nevermind, I found a video that helped me.

1 Like

I thought I would be able to just change some values for the up and down rotation, but it didn’t work. Would you by any chance know how to do that? This is the side to side rotation script.

local rep = game:GetService("ReplicatedStorage")
local event = rep:WaitForChild("mousePos")
local base = script.Parent.tank

event.OnServerEvent:Connect(function(plr, mousePosition)
	if mousePosition then
		local myX = (mousePosition.X - base.Attachment1.WorldPosition.X)
		local myY = (mousePosition.Z - base.Attachment1.WorldPosition.Z)
		local theta = math.atan2(myX, myY)
		script.Parent.turret.xHinge.TargetAngle = math.deg(theta)
	end
end)

Your overall idea is right, but there are some details to fix. Something like this might work:

event.OnServerEvent:Connect(function(plr, mousePosition)
	if mousePosition then
        local baseAtt1 = base.Attachment1
        local mousePosRelative = baseAtt1.WorldCFrame:PointToObjectSpace(mousePosition)
		local theta = math.atan2(mousePosRelative.Z, mousePosRelative.X)
		script.Parent.turret.xHinge.TargetAngle = math.deg(theta)
	end
end)

Just taking the world-space tank-to-mouse vector won’t work because it doesn’t deal with the tank itself being rotated. That’s why it converts to the tank-space tank-to-mouse vector. I might have flipped the X and Y to atan2 or something, can’t test it ATM.

This doesn’t work, I will attach a video of what it does.

Are you sure everything is rotated right?

I put a decal in it, and set it to be on the front face to see if the rotation is correct.


This is the script I have. It’s in workspace

game.ReplicatedStorage.mousePos.OnServerEvent:Connect(function(plr, mousePosition)
	if mousePosition then
		local baseAtt1 = workspace.base.Attachment1
		local mousePosRelative = baseAtt1.WorldCFrame:PointToObjectSpace(mousePosition)
		local theta = math.atan2(mousePosRelative.Z, mousePosRelative.X)
		workspace.barrel.HingeConstraint.TargetAngle = math.deg(theta)
	end
end)

The same thing is happening as shown in the video clip before. Do you know why it isn’t working?

Attachments can also be rotated, how about those?

It is rotating around the x axis, which is what I want. It’s just not rotating towards the mouse. Even so, here is how I set the rotation of the attachments. I set the target angle to 50 or something and saw if it was the right rotation. This is what it shows. It is the correct rotation, any other way I rotate the attachments makes it rotate around a different axis.

Oh I misunderstood then, thought you were talking about the yaw servo. Try this:

theta = math.atan2(mousePosRelative.Z, mousePosRelative.Y)

Still doesn’t work, not going to show video because it’s the same as before, going to random places.

My only remaining idea then is to try every combination of X, Y, Z, -X, -Y and -Z for the parameters to atan2. Try printing mousePosRelative to get some idea of how things are oriented incorrectly.

Does the order of the atan2 matter? (math.atan2(mousePosRelative.Z, mousePosRelative.Y) or math.atan2(mousePosRelative.Y, mousePosRelative.Z))? Also do I have to try the combinations of the same letter (Y,Y etc)

Yes, it matters. If the correct arguments are supplied but out of order or with the wrong sign, you should still get some movement that looks like it’s in the right plane but it may be inverted across either axis and/or be in the wrong direction.

Wish I could hop into Studio and look myself right now but I can’t, sorry :confused:

Any chance you could upload a video of moving the mouse around and printing the mousePosRelative?

Here, I have mousePosRelative printed.

Why don’t you want to use the lerp function?

The lerp function doesn’t create a realistic effect, it starts off slow goes faster and then slows down. What I want is a constant rotation speed, like in real tanks. I find that it overall feels nicer to have a constant rotation speed.