Clamp camera movement relative to another part

Trying to code the camera for a turret, where the players camera movement is limited. Currently the code I have clamps the camera but does it relative to the world direction instead of the turret direction

local rX, rY, rZ = Camera.CFrame:ToOrientation()
local limX = math.clamp(math.deg(rX), -45, 45)
local limY = math.clamp(math.deg(rY), -45, 45)
local clampedOrientation = CFrame.fromOrientation(math.rad(limX), math.rad(limY), rZ)
Camera.CFrame = CFrame.new(Camera.CFrame.p) * clampedOrientation

I tried changing it to be relative to its reference part (CamPart) but that just breaks it entirely:

local CamPart = Turret.CamPart -- Reference part for the cameras origin
local relativeCF = Camera.CFrame:ToObjectSpace(CFrame.lookAt(Camera.CFrame.Position, CamPart.CFrame.LookVector, CamPart.CFrame.UpVector))
local rX, rY, rZ = relativeCF:ToOrientation()
			
local limX = math.clamp(math.deg(rX), -45, 45)
local limY = math.clamp(math.deg(rY), -45, 45)
local clampedOrientation = CFrame.fromOrientation(math.rad(limX), math.rad(limY), rZ)
Camera.CFrame = CFrame.new(Camera.CFrame.p) * clampedOrientation

This is looped using RunService:BindToRenderStep("TurretControl",Enum.RenderPriority.Camera.Value + 1, controlLoop)

1 Like

I have done this for my module which is on my profile.

It should look something like this:

local baseCFrame : CFrame
	if turretBase:IsA("Attachment") then
		baseCFrame = turretBase.WorldCFrame-turretBase.WorldCFrame.Position
	else
		baseCFrame = turretBase.CFrame-turretBase.CFrame.Position
	end

	local relativeToWorld = currentJointMotor6D.Part0.CFrame:Inverse()
	local lookAtWorld = CFrame.lookAt(turretPosition,lookAtPosition,baseCFrame.UpVector)--goal LookAt CFrame

	local goalCFrame

	if self.Constraints then
		local turretRelativeCF = baseCFrame:ToObjectSpace(lookAtWorld)
		local x , y , z = turretRelativeCF:ToOrientation()
		--print(math.deg(x),math.deg(y),math.deg(z))
		local constrainedX , constrainedY = self:EulerClampXY(x,y)

		--Detect quadrant of lookAt position
		local jointPosition = currentJointMotor6D.Part0.CFrame*originalC0Position
		local quadrantLookAtFromJointPosition = CFrame.lookAt(jointPosition,lookAtPosition,baseCFrame.UpVector)	
		local baseRelative = baseCFrame:ToObjectSpace(quadrantLookAtFromJointPosition)
		local _,y, _ = baseRelative:ToOrientation()
		constrainedY = math.abs(constrainedY)*math.sign(y)--use the quadrants of the lookAtFromJoint
		--print(math.deg(constrainedX),math.deg(constrainedY))
		--print(math.deg(constrainedY))
		goalCFrame = relativeToWorld*baseCFrame*CFrame.fromOrientation(constrainedX,constrainedY,z)*turretCFrameRotationOffset
	else
		goalCFrame = relativeToWorld*lookAtWorld*turretCFrameRotationOffset
	end

The key is converting it relative to a baseCFrame, then comverting it back to world space

1 Like

Im having some trouble implementing this, it just makes my camera act crazy:

heres my code:

local lookAtPosition = Camera.CFrame.LookVector
local jointPosition = Camera.CFrame.Position
			
local relativeToWorld = Camera.CFrame:Inverse()
local baseCFrame = CamPart.CFrame - CamPart.CFrame.Position
local lookAtWorld = CFrame.lookAt(CamPart.CFrame.Position,lookAtPosition,baseCFrame.UpVector)--goal LookAt CFrame
			
local relativeCF = baseCFrame:ToObjectSpace(lookAtWorld)
local rX , rY , rZ = relativeCF:ToOrientation()
			
local limX = math.clamp(math.deg(rX), -45, 45)
local limY = math.clamp(math.deg(rY), -45, 45)
			
local quadrantLookAtFromJointPosition = CFrame.lookAt(jointPosition,lookAtPosition,baseCFrame.UpVector)	
local baseRelative = baseCFrame:ToObjectSpace(quadrantLookAtFromJointPosition)
local _,y, _ = baseRelative:ToOrientation()
rY = math.abs(rY)*math.sign(y)--use the quadrants of the lookAtFromJoint

Camera.CFrame = relativeToWorld*baseCFrame*CFrame.fromOrientation(limX,limY,rZ)

i assumed lookAtPosition and jointPosition would be for the rotating part and baseCFrame would be what the rotating parts movement is based on

relative to world is not necessary, that is only for Motor6Ds since C0 is in object space.