Clamping Camera Y and X rotation causing camera jumps

I’m trying to limit the camera to a certain X and Y rotation that is grabbed by the Camera CFrame so the player cannot turn all the way around.

Here’s the script:

local freelookLowLimit, freelookHighLimit = 0,0
local Camera = workspace.CurrentCamera

local _, rY2 = Camera.CFrame:ToOrientation()
freelookLowLimit = math.deg(rY2)-60
freelookHighLimit = math.deg(rY2)+60
	
RunService:BindToRenderStep("Freelook", Enum.RenderPriority.Camera.Value, function()
	local rX, rY, rZ = Camera.CFrame:ToOrientation()

	local limY = math.clamp(math.deg(rY), freelookLowLimit, freelookHighLimit)
	local limX = math.clamp(math.deg(rX), -70, 70)
	
	Camera.CFrame = CFrame.new(Camera.CFrame.Position) * CFrame.fromOrientation(math.rad(limX), math.rad(limY), rZ)
end)

Here’s a video of the “camera jumps” that are happening:

It looks like gimbal lock, which happens when you rotate a CFrame by 90 degrees. Basically the Axes of 2 of the rotations end up in the same place and affect each other.
Try typing “gimbal lock” into the search tool up top to see if those posts can help you out.

1 Like

Thanks for the response, this seems to be a bit out of my comfort zone.

I did some research and found this post but none of the solution seem to work.

New code:

local _, rY2 = Camera.CFrame:ToOrientation()
local freelookLowLimit = math.floor(math.deg(rY2)-60)+0.001
local freelookHighLimit = math.floor(math.deg(rY2)+60)+0.001
	

RunService:BindToRenderStep("UpdateLoop", Enum.RenderPriority.Camera.Value, function()
	local rX, rY, rZ = Camera.CFrame:ToOrientation()

	local limY = math.clamp(math.deg(rY), freelookLowLimit, freelookHighLimit)
	local limX = math.clamp(math.deg(rX), -70, 70)

	Camera.CFrame = CFrame.new(Camera.CFrame.Position) * CFrame.fromOrientation(math.rad(limX), math.rad(limY), rZ)
end)

I’ll see what I can do though.

I merely skimmed this thread but if you’re having the same issue I was, I think that I was able to resolve it.

I’ll take a look at my code and report back (if i remember lol). In the meantime, check out AxisAngles’s twitter, he posts useful tricks like how to overcome stuff like this

1 Like

I believe the issue is not the script itself.

But the default camera scripts.

You should look into the BaseCamera starter scripts since your script is not set to scriptable which means there is possible interference.

image

The code portion that does the rotation, perhaps its the order or that you should clamp the rotation input instead of the CFrame.

function BaseCamera:CalculateNewLookCFrameFromArg(suppliedLookVector: Vector3?, rotateInput: Vector2): CFrame
	local currLookVector: Vector3 = suppliedLookVector or self:GetCameraLookVector()
	local currPitchAngle = math.asin(currLookVector.Y)
	local yTheta = math.clamp(rotateInput.Y, -MAX_Y + currPitchAngle, -MIN_Y + currPitchAngle)
	local constrainedRotateInput = Vector2.new(rotateInput.X, yTheta)
	local startCFrame = CFrame.new(ZERO_VECTOR3, currLookVector)
			
	local newLookCFrame = CFrame.Angles(0, -constrainedRotateInput.X, 0) * startCFrame * CFrame.Angles(-constrainedRotateInput.Y,0,0)
	
	return newLookCFrame
end
1 Like

I think I found the error.

This post explains how roblox handles adding and subtracting orientations. The errors seemed to be lines:

local _, rY2 = Camera.CFrame:ToOrientation()
local freelookLowLimit = math.floor(math.deg(rY2)-60)+0.001
local freelookHighLimit = math.floor(math.deg(rY2)+60)+0.001

I fixed this by using:

local ChangeCFrame = PreviousCameraCFrame.Rotation:ToObjectSpace(Camera.CFrame.Rotation)

and manually checking the Y degrees if it exceeded it.

local _, Y, _ = ChangeCFrame:ToOrientation()

if Y > 60 then
  -- Set to 60
elseif Y < -60 then
  -- Set to -60
end

If it did exceed it, I would manually set the Y orientation of the camera to whatever it was clamped to.

Thank you for all your help!

1 Like

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