Hi! A little update, because I’ve made a lot of progress and it’s gotten close to working perfectly. This is the current code(a little jank, I apologise).
local maxTilt = 60
local iniX,iniY,_ = camera.CFrame:ToEulerAnglesYXZ()
local minY = math.deg(iniY) - maxTilt
local maxY = math.deg(iniY) + maxTilt
renderStep = RunService.RenderStepped:Connect(function(deltaTime)
local x,y,z = camera.CFrame:ToEulerAnglesYXZ()
y = math.rad(math.clamp(math.deg(y),minY, maxY))
camera.CFrame = CFrame.new(camera.CFrame.Position) * CFrame.fromOrientation(x,y,z)
end)
Works as intended! Sort of… There’s still a few kinks to iron out.
It’s kind of difficult for me to interpret the issue, so here are some Paint illustrations.
This is a rough sketch of the top down view of the player/camera, Negative Z is the direction looking at the “Front” part in my videos.
The purple line(henceforth called vP for Vector Purple) is the direction the player was looking before starting the loop. From vP, we draw 2 more lines, each 60 degrees apart in different directions from vP, these line will be the bounds which limit the player’s camera’s movement.
As can be seen, there is no issue with the system when vP is on the upper half of the circle, and, depending on the
maxTilt
, a little under the lower half as well(seen below).
So far so good! It’s only until the area between the black bars go through the 180 degree point that problems arise.
Let’s assume vP is pointing at 170 degrees, already there are problems. Looking back at the math for the area, the issue is obvious.
local minY = math.deg(iniY) - maxTilt
local maxY = math.deg(iniY) + maxTilt
With vP at 170 or -170, the range between min and max would be [110; 230] and [-230; 110] respectively, which is impossible and requires a bit more math to calculate the “overflow”(?), but would not be too hard to implement.
The main issue comes from when the player moves the mouse.
The turquoise line(referred as lV for Look Vector) stands in for the direction the player is looking at. Let’s look back at the code again to see where the problem lies.
y = math.rad(math.clamp(math.deg(y),minY, maxY))
or, in this case
y = math.rad(math.clamp(math.deg(y), -130, 110)) --Correct parameters of [110; 230]
Now, when the player moves the lV past the 180 degree mark, its orientation goes from positive to negative, let’s assume that negative orientation is -170 degrees. Because it is lower than the min(-130), it immediately jumps to -130 and creates a “dead zone” of sorts between 180 and -130 where the camera cannot turn to, which would restrict the camera’s field of movement to somewhere around this.
I don’t believe I’m even half as smart enough to find a solution to this. If you could help that would be amazing.