Joints

Note:Joints have been superseded by Constraints.


Joints are a way to connect two parts together. Many joints are created automatically using the Surface of parts. Joints can also be created manually using either the Command Bar or through a Script.

Types of joints[edit]

Weld, Snap, ManualWeld[edit]

Weld, Snap and ManualWeld are all a type of rigid joint which holds two parts together. If one part is moved or rotated, the other will likewise move and rotate to maintain the same orientation. If one part is anchored then neither part will be able to move. These joints are all functionally identical, the primary difference is how they are generated. See #Automatic Creation for the circumstances when they are created.

Glue[edit]

Glue is a type of joint that loosely holds two parts together. Unlike the rigid joints such as Weld, a Glue joint can break under enough force. Glue can be made through the Surface tool (see #Automatic Creation) but can also be made through scripts. When creating a Glue joint through a script, it is important to define a face. This face is defined relative to the joint position and the size determines how strong the joint is (the larger the area of the face, the more force is required to break the joint).

The Glue’s face is defined by four points F0, F1, F2 and F3. Each of these properties is a Vector3 which indicates the offset from the joint point. For glue to work as expected all of these points should be coplanar and the joint point should be on the plane.

See Glue for more on how to configure Glue.

Rotate[edit]

The Rotate joint is used to allow parts to freely rotate about the joint point (albeit only about one axis). Rotate joints are most commonly created through the Hinge surface, but can be made in scripts as well. When making a Rotate through a script it is recommended to make sure the parts involved are in the desired position before making the joint rather than relying on the snapping behavior of making joints.

Motor and Motor6D[edit]

Motor and Motor6D are both rotating joints which can be driven by an internal force. In both joints the desired rotation of the joint can be set with DesiredAngle and the rate of rotation can be set with MaxVelocity. The main difference between the two joints are that Motor6Ds are designed for use in character animations. The Motor6D allows for rotation about 3 axis. Currently the only way to access this functionality is through the Animation plugin. These joints are similar to Weld joints in the sense that they snap the parts together.

RotateV[edit]

RotateV is a rotating joint which is driven by an internal force. The rate of rotation is not a property of the joint, but actually set by the surface input of the joint’s Part0. The face is determined by where Part1 is relative to Part0. The surface inputs to note are Sin and Constant. Sin will oscillate the rotation, while Constant will rotate the joint at a constant velocity. RotateVs are most commonly made through the Motor surface type, but can be made through scripts as well. If making the joint through a script it is recommended to make sure the parts involved are in the desired position before making the joint rather than relying on the snapping behavior of making joints.

RotateP[edit]

RotateP is a rotating joint which is driven by an internal force. This joint attempts to maintain a set angle of rotation which requires a great deal of force to overcome. This rotational position is not set through the joint itself but rather set by the surface input of the joint’s Part0. The face is determined by where Part1 is relative to Part0. The surface inputs to note are Sin and Constant. Sin will oscillate between two points, while Constant attempt to maintain the set angle. RotatePs are most commonly made through the SteppingMotor surface type, but can be made through scripts as well. If making the joint through a script it is recommended to make sure the parts involved are in the desired position before making the joint rather than relying on the snapping behavior of making joints.

About Surface Parameters[edit]

All parts have 12 parameter properties, two for each surface. These are called <Surface>ParamA and <Surface>ParamB. They only affect RotateV and RotateP joints (which are also Motor and StepperMotor surface joints, respectively). The SurfaceParameter properties only affect anything when the InputType is either Constant or Sin.

If the InputType is Constant, the ParamA is ignored. For a RotateV joint, the ParamB defines the speed at which the joint rotates, and for a RotateP joint, the ParamB defines the angle which the joint moves towards.

If the InputType is Sin, the ParamA is the amplitude of the oscillation (Radians/sec for RotateV, Radians for RotateP). The ParamB is the frequency in radians per second, meaning one full oscillation is 6.28/ParamB seconds long.

Automatic Creation[edit]

The Surface property of parts can be used to create joints automatically if two compatible SurfaceTypes are brought next to each other. For example, if a surface with Studs is brought next to a surface with Inlets a Snap is created. The following chart shows the joint formed between all possible combinations of surfaces:

SmoothNoOutlines Unjoinable SteppingMotor Motor Hinge Universal Inlet Studs Weld Glue Smooth
Smooth ManualWeld RotateP RotateV Rotate ManualWeld Weld Glue ManualWeld
Glue Glue Glue RotateP RotateV Rotate Glue Glue Glue Weld Glue
Weld Weld Weld RotateP RotateV Rotate Weld Weld Weld Weld
Studs RotateP RotateV Rotate Snap Snap
Inlet RotateP RotateV Rotate Snap ManualWeld
Universal RotateP RotateV Rotate Snap
Hinge Rotate Rotate *Rotate / RotateP *Rotate / RotateV Rotate
Motor RotateV RotateV *RotateV / RotateP RotateV
SteppingMotor RotateP RotateP RotateP
Unjoinable
SmoothNoOutlines ManualWeld

The yellow-shaded cells containing ManualWeld above indicate the joints are only created if the Join setting in Studio to “Always”. These will not be created if the setting is "Surface only". Calling MakeJoints will also not create these.

There are a couple of special cases to keep in mind:

  • Rotating surfaces (Hinge, Motor and SteppingMotor) all show a 3d adornment representing the joint. This adornment must be inside the other part for a joint to be created for these surfaces.
  • If two rotating surfaces are brought together (and both parts cover the 3d adornment), then the surface on the part with the larger size dimensions will determine the joint. For example, if a small part with a Hinge is brought next to a larger part with a Motor, then a joint for the Motor will be created. If the two parts are the same size, then the surface of the selected part will determine the joint. These cases are italicized
  • If two joinable surfaces are brought together, certain types of joints will be prioritized. For example, if a weld surface is brought next to a glue surface, a Weld joint will be created.

Programmatic Creation[edit]

Joints can also be made in code either through the Command Bar or in a Script.

All joints are derived from the JointInstance class, meaning that while they each have some special properties that can be set, the creation between all joints is pretty much the same. There are 4 properties in particular that have to be set for a joint to work properly:

Part0 and Part1[edit]

Part0 and Part1 refer to the two parts that are connected by the joint. Given two parts either could be Part0 or Part1, it isn’t critically important which part is assigned to each. It is general convention though that if a part is considered a base for the weld (particularly if a motor is involved) then that part is assigned to Part0.

C0 and C1[edit]

C0 and C1 refer to the CFrame of the connection points of the joint and define how the two joined parts will be positioned and rotated in relation to one another. Also, if our joint is a rotating part (such as on a hinge), C0 and C1 will define where that rotation will occur. For now we will just be concerned with the position component of C0 and C1.

Position[edit]

To better understand C0 and C1 we’ll first concentrate on the position component. Consider an example using the Weld joint. This type of joint is very simple in that is just keeps two parts locked together. No matter how much one part is moved or rotated, the other part will always remain oriented the same compared to the moving part. To make sure the parts stay connected with a Weld though, we have to say where they are in relation to each other. To do this we picture a point where we want the joint to be. We then say how far the point is from the center of Part0, and then how far the point is from the center of Part1. We do this by defining the position of C0 and C1 (which correspond to Part0 and Part1 respectively)

Consider the following code:

local base = game.Workspace.Base
local part = game.Workspace.Part
 
local weld = Instance.new("Weld")
weld.Part0 = base
weld.Part1 = part
weld.C0 = CFrame.new(0,0,0)
weld.C1 = CFrame.new(3,0,2)
weld.Parent = game.JointsService

In the above code we are taking two parts, one called base the other called part, and we connect them together using a Weld joint. By setting C0 to 0,0,0 we are telling the joint that the joint point is in the middle of Part0 (which is base). We then say to get from Part1 (which we called part) to that point, we need to go 3 studs in the positive X direction and 2 studs in the positive Z direction. If we run the code, the two parts will snap like this:

JointExample0.png

The hinges were added to indicate the back of the part which is the direction of positive Z.

The point does not necessarily have to be the center of a part. It is perfectly valid for the joint point to be on the edge of a part, even outside of both parts. Consider the following code:

local base = game.Workspace.Base
local part = game.Workspace.Part
 
local weld = Instance.new("Weld")
weld.Part0 = base
weld.Part1 = part
weld.C0 = CFrame.new(-2,0,0)
weld.C1 = CFrame.new(3,0,2)
weld.Parent = game.JointsService

In the above the point of the joint will be 2 studs in the negative X direction from Part0. The point will also be 3 studs in the positive X and 2 studs in the positive Z from Part1. In this example, even though the two parts aren’t touching they are still fixed together and will not move in relation to each other.

JointExample1.png

Rotation[edit]

C0 and C1 can also include rotation as they are both CFrames. When a joint is made both Part0 and Part1 will be rotated about C0 and C1 respectively so that C0 and C1 line up.

Lets take a look at an example:

local base = game.Workspace.Base
local part = game.Workspace.Part
 
local weld = Instance.new("Weld")
weld.Part0 = base
weld.Part1 = part
weld.C0 = CFrame.new(0,0,3) * CFrame.Angles(math.rad(45),0,0)
weld.C1 = CFrame.new(0,-1,0)
weld.Parent = game.JointsService

JointsExample2.png

This code will place the joint point 3 studs in the positive Z from Part0 and 1 stud below Part1. We also rotated C0 by 45 degrees about the X axis by multiplying it by another CFrame. Since C0 is rotated like this, Part1 had to be rotated accordingly. See the following animation to see what is going on:

JointExample2.gif

Both CFrames can be rotated like this. For rigid joints like welds this is not usually necessary, but it will prove handy when we look at Motors later. Let’s look at another example:

local base = game.Workspace.Base
local part = game.Workspace.Part
 
local weld = Instance.new("Weld")
weld.Part0 = base
weld.Part1 = part
weld.C0 = CFrame.new(-0,0,3) * CFrame.Angles(math.rad(45),0,0)
weld.C1 = CFrame.new(0,-1,0) * CFrame.Angles(math.rad(45),0,0)
weld.Parent = game.JointsService

JointsExample3.png

Notice how the positions were not changed from the example before, but now both C0 and C1 are being rotated. Since they are both being rotated by the same amount, both CFrames will be oriented in the same direction, meaning neither Part0 nor Part1 need to be rotated. Let’s take a look at another animation:

JointExample3.gif

Common Join Function[edit]

It is not always necessary to hardcode the values for C0 and C1. If you want to create a joint between two parts and like their orientation the following function is commonly used:

local function WeldTogether(Part0, Part1, JointType, WeldParent)
    --- Weld's 2 parts together
    -- @param Part0 The first part
    -- @param Part1 The second part (Dependent part most of the time).
    -- @param [JointType] The type of joint. Defaults to weld.
    -- @param [WeldParent] Parent of the weld, Defaults to Part0 (so GC is better).
    -- @return The weld created.
 
    JointType = JointType or "Weld"
 
    local NewWeld = Instance.new(JointType)
    NewWeld.Part0  = Part0;
    NewWeld.Part1  = Part1;
    NewWeld.C0     = CFrame.new();
    NewWeld.C1     = Part1.CFrame:toObjectSpace(Part0.CFrame);
    NewWeld.Parent = WeldParent or Part0;
 
    return NewWeld
end

Note that if you are using a rotating joint you will still have to rotate C0 and C1 to change the axis of rotation.

Rotating Joints[edit]

Several types of joints allow rotation. By default, the rotation is always about the Z (forward axis). The point of rotation will be the point setup by the C0 and C1 properties of the joint. If a different axis of rotation is desired then C0 and C1 will have to be rotated.

Lets take a look at a few examples of rotating joints. In these we will use the Motor joint which rotates the joined parts at a set velocity until a rotational goal has been met. Consider the following code:

local base = game.Workspace.Base
local part = game.Workspace.Part
 
local motor = Instance.new("Motor")
motor.Part0 = base
motor.Part1 = part
motor.C0 = CFrame.new(0,0,1)
motor.C1 = CFrame.new(0,0,-1)
motor.Parent = game.JointsService
 
motor.MaxVelocity = math.rad(3)
motor.DesiredAngle = math.rad(360)

This code will join the two parts together and then tell the motor to make a full rotation. Here is the result (the blue part is shown to visualize the axis of rotation):

MotorExample0.gif

As mentioned earlier, we can change the point of rotation by changing C0 and C1. For example, we can put the point of rotation at the edge of the part:

local base = game.Workspace.Base
local part = game.Workspace.Part
 
local motor = Instance.new("Motor")
motor.Part0 = base
motor.Part1 = part
motor.C0 = CFrame.new(2,0,1)
motor.C1 = CFrame.new(2,0,-1)
motor.Parent = game.JointsService
 
motor.MaxVelocity = math.rad(3)
motor.DesiredAngle = math.rad(360)

Notice how the rate and direction of rotation hasn’t changed, we just changed where the rotation occurs.

MotorExample1.gif

What if we wanted to change the axis of orientation? For example, what if we wanted the part to swing like a door? All we have to do is rotate C0 and C1. Since we want the parts to rotate about the Y axis (as opposed to the Z), we just have to rotate by 90 degrees in X. Note how as seen #ABOVE if we rotate both C0 and C1 the parts will stay oriented the same way:

local base = game.Workspace.Base
local part = game.Workspace.Part
 
local motor = Instance.new("Motor")
motor.Part0 = base
motor.Part1 = part
motor.C0 = CFrame.new(2,0,1) * CFrame.Angles(math.rad(90),0,0)
motor.C1 = CFrame.new(2,0,-1) * CFrame.Angles(math.rad(90),0,0)
motor.Parent = game.JointsService
 
motor.MaxVelocity = math.rad(3)
motor.DesiredAngle = math.rad(360)

Again the rate of rotation is the same, but the axis has changed since we rotated C0 and C1.

MotorExample2.gif