How to prevent part from rotating past a certain point?

I have a script that rotates part of a model by holding down a key.
It does move correctly, but when it overlaps or goes too far, it bugs out and switches places.

Here are the scripts which control that part:

--client (StarterPlayerScripts)--

local REP = game:GetService("ReplicatedStorage")
local UIS = game:GetService("UserInputService")

local remote = REP.FK1

UIS.InputBegan:Connect(function(input, gp)
	if gp then return end
	if input.KeyCode == Enum.KeyCode.G then
		remote:FireServer(true)
	end
end)

UIS.InputEnded:Connect(function(input, gp)
	if gp then return end
	if input.KeyCode == Enum.KeyCode.G then
		remote:FireServer(false)
	end
end)
--server (ServerScriptService)--

local REP = game:GetService("ReplicatedStorage")
local RS = game:GetService("RunService")

local remote = REP.FK1

local Digit1 = game.Workspace.RobotArm.Claw.DigitsKnuckles.Digit1
local Digits

RS.Heartbeat:Connect(function()
	if Digits then
		local x,y,z = Digit1.CFrame:ToOrientation()
		Digit1:PivotTo(CFrame.Angles(x - math.rad(-2), y, z) + Digit1:GetPivot().Position)
	end
end)

remote.OnServerEvent:Connect(function(plr, state)
	Digits = state
end)

Any way to fix this?

1 Like

The trick is to store the “resting”, or “bind” position of the joint when the game starts. You then need to keep your angle separate, which you can clamp to some +/- value, then calculate the transform from those two things. The reason its flipping is because ToOrientation gives a unique value, it does not handle wrapping around smoothly like a quaternion.

1 Like

You can look up the term gimbal lock to describe the condition when one of the x,y,z rotations aligns with one of the other ones so that rotating either one does the same thing.
Search the forums with the term “prevent gimbal lock” and you’ll see a few posts on how to prevent it using quaternions like @azqjanna said.