CFrame Troubles

I cannot figure out how to get the opposite of what I have.

I want the turret to be able to rotate on the oppisite side of the platform: from 90 to -90 (yellow side), not from -90 to 90 (green side).

When I try changing the numbers I get the following error:

...invalid argument #3 to 'clamp' (max must be greater than or equal to min)

I tried using 90 and 270 but that doesn’t work. It will only rotate from 90 to 180 (yellow side) then jump back to 90.

Here is the script if anyone can help me understand what’s going wrong:

seat:GetPropertyChangedSignal("Occupant"):Connect(function()
	if seat.Occupant then
		occupied = true
		while task.wait() do
			if occupied then
				-- find player and mouse postion
				local character = seat.Occupant.Parent
				local player = game.Players:WaitForChild(character.Name)
				local MouseLock = character:WaitForChild("RF_MouseLock")
				local MouseHitPosition = MouseLock:InvokeClient(player)
				-- rotate toward mouse
				if (MouseHitPosition-housing.Position).magnitude > 12 then

					local rotationCFrame = CFrame.new(housing.Position, MouseHitPosition)	
					local x, y, z = rotationCFrame:ToOrientation()
					local newYAngle = math.clamp(y, math.rad(-90), math.rad(90)) --limit right/left
					local newXAngle = math.clamp(x, math.rad(-45), math.rad(45)) --limit down/up
					local newRotationCFrame = CFrame.fromOrientation(newXAngle, newYAngle, z)
					
					housing.CFrame = newRotationCFrame + housing.Position
				end
			end
		end
	else
		occupied = false
		return
	end
end)

1 Like

Cannot figure this out. How do I get the gun to rotate only in the yellow half?

Mind linking me a copy of the place with the turret so I can test? I’ll get it sorted out for you.

This means that the minimum value you set was bigger than the maximum value (so like min of 90, max of -90) which makes no sense and thus errors

You can try setting the min to 90 and the max to 270, however, orientation can be negative so that could mess it up. You can either add 360 to it if it’s negative, or you can get the angle with math.atan2, which uses some trigonometry.

I look forward to seeing what you can come up with!

I’ve been working on this thing for 3 days.

Turret.rbxl (77.0 KB)

Extremely sorry for the delay, I got caught up in a few things and completely forgot about this post until I laid in bed and randomly remembered. This should do what you want it to do.

local function clamp(a: number)
	local b = nil;
	b = math.abs(a)
	b = math.clamp(b, math.rad(90), math.rad(180))
	return a < 0 and -b or b
end

local newYAngle = clamp(y)

1 Like

You’re a project saver!

Thank you so much!

1 Like

All your calculations are in world space though, so if you want these turrets to be able to face anywhere in game, you’ll need to add in a world to local space transform too. As-is, you can’t just rotate your model to change which way the installment faces.

If this is going to be used in a live game, I’d also strongly urge you not to do it this way. Adjusting CFrames on the server makes everything look stuttery on all clients. It won’t move smoothly with the camera of the person in the seat either. And polling the client for mouse position with a RemoteFunction?! That means the person in the seat will have their full round trip ping as input latency, or if you CFrame things locally too, server and client will be competing to set the part orientations (more stuttering). There’s no need to do any of this if you just use hinges, the position changes will replicate automatically because the player in the Seat will have network ownership of the turret. Hinges also let you set the angle limits, rotation speeds, etc. without having to build CFrames, you just set the angle and angle limits in degrees.

No problem. I second what Emily said though. I tested the time between the initial movement of the mouse and the movement of the turret and saw upwards of ~220ms at times. When you have that much of a delay, your players will not only have to account for any bullet velocity you set up, but the input delay as well - which isn’t optimal. Obviously feel free to do what your heart desires, but if it’s going to be used in a game I highly recommend moving over to physics or a more optimized system. If you move over to physics and keep network ownership on the client I’d run a few checks on the server though, as clients could very easily give themselves full (including unwanted) control of the turret’s position and rotation.

I tried using hinges but could not figure out how to get a hinge to move to a mouse position.

I have another turret for a tank that uses hinges and it works great, but it moves with keys not the mouse position. I want quick easy movements and the keyboard doesn’t offer that.

I don’t understand why you think this is a bad idea.

What is the difference between the way I am doing it and having the Client send their mouse position through a Remote Event. It’s the same ammount of information either way.

There are some issues unique to RemoteFunctions that call a client from a server, especially if it’s done rapidly, like every frame. Unlike RemoteEvents, they yield waiting for a response. This can be a problem if the client doesn’t respond, a reason most devs avoid RemoteFunctions entirely. For something like user input, it just adds a ton of lag. RemoteFunctions are also slower than implementing the same system with RemoteEvents, even when used correctly.

No, because you don’t actually need to send any information from server to client. If someone’s in the seat, they can send their MousePosition to the server. You eliminate having to send an event from server to client every frame to request the mouse position, which is entirely unnecessary to do. The RemoveEvent solution uses no server to client bandwidth, the RemoteFunction solution uses a lot.

Thank you for explaining.

Now that I understand the difference, I totally agree. You thinking makes good sense.

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.