Limit Y rotation

Hello everyone. im coding a turret for a project. the goal is that this turret aims w<here the mouse of the player is pointing. so far I was able to achieve that with this code:

local cframeToSet = CFrame.new(turret.muzzle:GetPrimaryPartCFrame().p,aimToPosition) turret.muzzle:SetPrimaryPartCFrame(cframeToSet)

Now I also want that this current only can aim at a certain angle to the sky. I know that I can use math.clamp for this. Ive tried getting the angles of the primary part and clamping that (i don’t have the code for that anymore.). But it resulted in weird behavior. The part just started glitching. Does someone know a good approach to this ?

You can get the euler angles of the “cframeToSet” CFrame with the :ToEulerAnglesXYZ() method. The angles you are looking for are X and Z, since they are the ones that affect the vertical orientation.

Afterwards you’ll have to apply the CFrame with:

turret.muzzle:SetPrimaryPartCFrame(CFrame.new(cframeToSet.Position)*CFrame.Angles(your angles here))

Math.clamp seems to me as the way to go. The following code assumes you’re regularly passing the mouse.Hit.p to a remote event, but the same result can be achieved if performed locally.

local turret = game.Workspace.Turret
local MIN_HEIGHT = 0
local MAX_HEIGHT = 50
game.ReplicatedStorage.MyRemoteEvent.OnServerEvent:Connect(function(player,pos)
    local newPos = Vector3.new(pos.X,math.clamp(pos.Y,MIN_HEIGHT,MAX_HEIGHT),pos.Z)
    local cf = turret:GetPrimaryPartCFrame()
    turret:SetPrimaryPartCFrame(CFrame.lookAt(cf.Position,newPos))
end)
1 Like

I tried your answer and it is almost working. i implemented it like this:

    local cframeToSet = CFrame.new(turret.muzzle:GetPrimaryPartCFrame().p,aimToPosition)
    local x,y,z = cframeToSet:ToEulerAnglesXYZ()
    print(x .." " .. z)
    local x2 = math.clamp(x, -10,0)
    local z2 = math.clamp(z, -0,0) 

    turret.muzzle:SetPrimaryPartCFrame(CFrame.new(cframeToSet.Position)*CFrame.Angles(x2,y,z2))`


as you can see when I look at a certain point in the sky it points to the wrong side. also I made the upper part of the barrel studs. i want that the studs face is always the top face. is it possible to do that ?

I rewrote the code since I couldn’t figure out the exact reason for why it didn’t work when pointing at the skybox. The variable names and the model hierarchy is different since I had to recreate the turret, but it should be fairly easy to implement.

Instead of clamping angles themselves, I just clamped their unit vector so that it can never point higher than 0 on the Y axis. I added pos0 to avoid long term float errors and indexed PrimaryPart directly to avoid unnecessary method calls.

local turret = workspace.Model
local primpart = turret.PrimaryPart
local pos0 = primpart.CFrame.Position

local mouse = game:GetService("Players").LocalPlayer:GetMouse()
game:GetService("RunService").Heartbeat:Connect(function()
	local aimToPosition = mouse.Hit.Position
	
	local diraim = (aimToPosition-pos0).Unit
	diraim = diraim.Y<=0 and diraim or Vector3.new(diraim.X,0,diraim.Z)
	
	primpart.CFrame = CFrame.lookAt(pos0,pos0+diraim)
end)
1 Like