How to constrain joints on model to allow rotation in a specific direction

So I have this model thats broken into 3 parts:

3 . The bottom part is the base and doesn’t move, this can be anchored.
2 . The middle part is the joint and should stay locked to the base. Basically locked into position. However, it should be able to rotate left and right (ONLY).
1 . The top part should rotate left and right based on the joint part rotating left and right. However, it should also be able to rotate up and down independently of the joint part.

For example, top part rotating up and down

Joint part rotating left and right:

They need to be rotatable via scripting but stay locked otherwise.

How in the world do I accomplish this? I figure there is a Bodymover or gyro or constraint that will do this in combination?

This can be pretty easily achieved using Roblox’s Constraint system. In specific, you’d likely want 2 hinge constraints, 1 for each axis of rotation. I’d highly recommend against relying on any type of BodyMover for this scenario, as they’re not meant to handle this and you’d likely run into countless issues.

2 Likes

You were right, hinge joints were the way to go. Basically I just set my hinge from the base to the joint to rotate left and right. And From the joint to the Top part up and down.

I also found it easier to use BodyGyros to move the joint and the top part independently. To do this though I had to set ActuatorType to None so that the BodyGyros could do their thing (and they wouldnt fight each other).

I then just set the MaxTorque to 0 on the axis that the gyro is not supposed to move. For example:

This allowed it to move left or right.

Then to allow the top part to tilt up and down on that Parts HingeConstraint, I sent the body gyro this way:

I whipped up a little lua script to test this:

local chris = workspace.Characters:WaitForChild("chrisjd31")
local JointGyro = script.Parent.Joint.BodyGyro
local TopGyro = script.Parent.Top.BodyGyro

while wait(1) do
	JointGyro.CFrame = CFrame.new(script.Parent.Joint.Position, chris.HumanoidRootPart.Position) * CFrame.Angles(0,math.rad(180),0)
	TopGyro.CFrame = CFrame.new(script.Parent.Top.Position, chris.HumanoidRootPart.Position)
end

This was the end result:

The following articles were really helpful in me understanding the different constraints and how to set them properly: