Limiting CFrame Rotation

Currently I’ve been trying to limit the body gyro rotation (specifically the pitch) of my model through CFrame:ToEulerAnglesXYZ() like in the local script shown below:

while wait(0.1) do
	local x,y,z = SubRootPart.RotationGyro.CFrame:ToEulerAnglesXYZ()
    print(math.round(math.deg(x)))
	if WHeld == true and math.round(math.deg(x)) < 30 then
		SubRootPart.RotationGyro.CFrame = SubRootPart.CFrame * CFrame.Angles(math.rad(5), 0, 0)
	end
end

This works, sort of?
https://gyazo.com/3dfbe9d1b4af9328b12de8fb51ae9ccf

However, this doesn’t work so well after the model had rotated past a certain point (90 degrees i think) along its yaw, where the number changes to 180 and, at seemingly random, flips from negative to positive. Here’s just a few examples:
https://gyazo.com/67c34a35076bccbe5c98b36278657eee
https://gyazo.com/fcdc52401e6f4bca8f4ba93fe36d631f
https://gyazo.com/38d6fc925fe7fc59dc6c9551dd5f4cc3

I have seen other posts similar however I don’t quite understand them and I don’t wish to necro-bump them just to ask a question.

if WHeld == true and math.round(math.deg(x)) < 30 and math.round(math.deg(x)) > -30 then

Perhaps the order the angles are being applied to are causing the problem.

Here is an example project where I used CFrame.lookAt to make a turret look at a desired position then limited the angles using CFrame:To orientation() with math.clamp to limit the angle of elevation and depression. The problem should be similar to this one.

Edit: also how does your subrootpart look like, is the front face of this part oriented with the front face of the submarine model correctly?

I suggest making sure the root part is facing the correct direction in order to avoid having an offset rotation that needs to be CFramed in order to fix.

I actually saw your post on limiting CFrame rotation. However I don’t quite understand how I would use math.clamp in this situation.
And yes the orientation of the root part is at 0, 0, 0 and the model does move forward correctly. So I’d assume it is oriented correctly.

Hmm, if I were to apply what I did previously, I would do this:

while wait(0.1) do
    if WHeld == true then
		SubRootPart.RotationGyro.CFrame = SubRootPart.CFrame * CFrame.Angles(math.rad(5), 0, 0)
	end
	local x,y,z = SubRootPart.RotationGyro.CFrame:ToOrientation()
    local clampedX = math.clamp(math.deg(x),-30,30)--elevation and depression angles
    clampedX = math.rad(clampedX)
    SubRootPart.RotationGyro.CFrame = CFrame.fromOrientation(clampedX,y,0)
end

This piece of code clamps the elevation and depression angle of the model assuming the model has no Z-axis roll because if it did have Z axis roll things would get a little more confusing and the X angle won’t represent the angle of elevation/depression from the horizontal surface but I’ll suggest you see that for yourself if the code piece does work.

    SubRootPart.RotationGyro.CFrame = CFrame.fromOrientation(clampedX,y,z)
1 Like