What do you want to achieve? Keep it simple and clear!
I want to limit camera to rotate mostly to one side than other, like in this video:
I need to make It make camera rotatation don’t go to the left completely and turn almost all the way around to the right.
What is the issue? Include screenshots / videos if possible!
Basically it looks like this:
What solutions have you tried so far? Did you look for solutions on the Developer Hub?
I’ve tried doing this in BaseCamera module that is in PlayerModule:
function BaseCamera:CalculateNewLookCFrameFromArg(suppliedLookVector: Vector3?, rotateInput: Vector2): CFrame
local currLookVector: Vector3 = suppliedLookVector or self:GetCameraLookVector()
local currPitchAngle = math.asin(currLookVector.Y)
local currPitchAngleX = math.asin(currLookVector.X)
if player.Character and player.Character.Humanoid:GetAttribute("Gripping") then
if MAX_X == math.rad(90) and MIN_X == math.rad(-90) then
local rX,rY,rZ = workspace.CurrentCamera.CFrame:ToOrientation()
MAX_X = math.rad(rX + 45)
MIN_X = math.rad(rX - 10)
end
MAX_Y = math.rad(30)
MIN_Y = math.rad(-60)
else
MIN_Y = math.rad(-80)
MAX_Y = math.rad(80)
MAX_X = math.rad(90)
MIN_X = math.rad(-90)
end
local yTheta = math.clamp(rotateInput.Y, -MAX_Y + currPitchAngle, -MIN_Y + currPitchAngle)
local xTheta = math.clamp(rotateInput.X, -MAX_X + currPitchAngleX, -MIN_X + currPitchAngleX)
local constrainedRotateInput = Vector2.new(xTheta, 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
There’s probably a better way to do this, but it works and what this does is that it limits the X axis
local Camera = workspace.CurrentCamera
local X_Min = -30
local X_Max = 30
game:GetService("RunService").RenderStepped:Connect(function()
local CameraPitch,_,_ = Camera.CFrame:ToOrientation()
local XInDegrees = math.deg(CameraPitch)
local ClampedX = math.clamp(XInDegrees,X_Min,X_Max)
local dif = XInDegrees - ClampedX
if dif > 0.1 or dif < -0.1 then
Camera.CFrame *= CFrame.Angles(math.rad(-dif),0,0)
end
end)
It limits camera rotatation based on up and down movement, and I want to limit it going to the left completely and turn almost all the way around to the right.
so i think the reason why his script is clamping the y instead of the x is because ToOrientation (i actually just found this out) is apparently mimicking the ToEulerAnglesYXZ instead of the ToEulerAnglesXYZ. the difference being the y and x are flipped. i have no clue why roblox decided to make it output in yxz form instead of xyz form but it is what it is i guess so bassically just change
local CameraPitch,_,_ = Camera.CFrame:ToOrientation()
to
local _,CameraPitch,_ = Camera.CFrame:ToOrientation()
and now it should work perfectly.
anyway i tried testing this in studio and to my suprise… it didnt work.
so after lots of random testing and looking around on the documentation page i finally realized that in this line
it works. i have no clue why CFrame.Angles seems to be using yxz format because on the documentation it actually says it should be zyx but in game it says xyz but actually its yxz so honestly i have no idea anymore which it is but all you need to know is that the second of these two lines makes it work for some reason.
TLDR:
this works
local Camera = workspace.CurrentCamera
local X_Min = -30
local X_Max = 30
game:GetService("RunService").RenderStepped:Connect(function()
local _,CameraPitch,_ = Camera.CFrame:ToOrientation()
local XInDegrees = math.deg(CameraPitch)
local ClampedX = math.clamp(XInDegrees,X_Min,X_Max)
local dif = XInDegrees - ClampedX
if dif > 0.1 or dif < -0.1 then
Camera.CFrame *= CFrame.Angles(0,-math.rad(dif),0)
end
end)
I thought you meant the Pitch/Up and Down Axis. Since, the post title said X rotation… so… I was confused since X is Pitch in Orientation. Anyways, here’s what you wanted.
local Camera = workspace.CurrentCamera
local Y_Min = -30
local Y_Max = 30
local Player = game.Players.LocalPlayer
local Character = Player.Character
local Root = Character.HumanoidRootPart
game:GetService("RunService").RenderStepped:Connect(function()
local _,RootYaw,_ = Root.CFrame:ToOrientation()
local RootYawInDeg = math.deg(RootYaw)
local Y_CalculatedMin = RootYawInDeg + Y_Min
local Y_CalculatedMax = RootYawInDeg + Y_Max
local _,CameraYaw,_ = Camera.CFrame:ToOrientation()
local YInDegrees = math.deg(CameraYaw)
local ClampedY = math.clamp(YInDegrees,Y_CalculatedMin,Y_CalculatedMax)
local dif = YInDegrees - ClampedY
if dif > 0.1 or dif < -0.1 then
Camera.CFrame *= CFrame.Angles(0,math.rad(-dif),0)
end
end)
Make sure to only use this when the Character’s Root Can’t rotate left and right or else it’ll look weird… (example, when climbing, sitting, or when the humanoid has autorotate off.) since the Rotation Limit is related to the Character HumanoidRootPart.
It should look like this after you apply it, there’s a little bit of jitter when the camera reaches the rotation limit but I’ll leave it to you to fix it.
This kinda worked, but when i tried tweaking the limit so it was able to go to the right more than left, this happens:
basically I set max to 10 and minimum to 70
local _,RootYaw,_ = HumanoidRootPart.CFrame:ToOrientation()
local RootYawInDeg = math.deg(RootYaw)
local Y_CalculatedMin = RootYawInDeg + -70
local Y_CalculatedMax = RootYawInDeg + 10
local _, CameraYaw,_ = Camera.CFrame:ToOrientation()
local YInDegrees = math.deg(CameraYaw)
local ClampedY = math.clamp(YInDegrees, Y_CalculatedMin, Y_CalculatedMax)
local Difference = YInDegrees - ClampedY
if Difference > 0.1 or Difference < -0.1 then
Camera.CFrame *= CFrame.Angles(0,math.rad(-Difference),0)
end