Skip to content

Instantly share code, notes, and snippets.

@jovannic
Last active November 8, 2022 05:27
Show Gist options
  • Star 7 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jovannic/6fdfb6d14eb12f7210de806f5f86cf5a to your computer and use it in GitHub Desktop.
Save jovannic/6fdfb6d14eb12f7210de806f5f86cf5a to your computer and use it in GitHub Desktop.
The Truth About Welds

Since we don't have this documented anywhere, I'll explain real quick.

The Truth About Welds

Weld, Snap, WeldConstraint, Motor, and Motor6D joints all combine multiple parts into the same Assembly. An assembly is a rigid body if none of it's parts are anchored. No physical forces can ever separate the parts of an Assembly or move them relative to each other unless the joints are removed or updated. They're a single body.

Every Assembly has a root part, see BasePart:GetRootPart. When a weld is C0/C1 is modified the root part will stay where it was.

Welds do not have any directionality. Part0 or Part1, doesn't matter. You can imagine rigid joints forming a tree branching down from the root part. All the parts down the tree from root will move, and their welded "children" in this tree will move with them.

The root part is picked based on the surface area of the largest face of a part's object aligned bounding box (defined by Size). A Humanoid's HumanoidRootPart has a 10x multiplier and a Seat has a 20x multiplier. All else being equal it will sort based on the replicated internal ID of the part. Root selection is deterministic and has to be because we rely on it for physics replication, but externally it's effectively random. Basically it's impossible for you to determine which part will be root ahead of time. Yes, root selection is... odd.

image image

A typical Roblox avatar is a single assembly. Here's a visualization of this tree in a basic R15 humanoid rig on the left, and a representation of this implicit tree of which parts move relative to which parts on the right.

It's actually been this way forever. Coincidences and occasional bugs have make this behavior hard to intuit.

Caution!!!

You should avoid relying on a particular part being root and generally try to write code that works agnostic of this. For example: the newer WeldConstraint avoids this by forcing you to position the two parts correctly how you want relative to each other, and just locks that relative orientation in as soon as it is enabled. It doesn't matter which part is root. You move the parts how you want to and we make sure it stays that way.

You should avoid relying on specifics of this implementation where possible. We're not completely satisfied with this system, but it's very risky to change it. Last time we tried to increase the root weight multiplier for HumanoidRootPart several popular games broke. We do have plans to rewrite some of these systems in the future to clean some of this up and allow for more control, but we plan these changes cautiously and try very hard to minimize breaking changes.

I hope this helps understand and work with it in the meantime.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment