It works this way because of the way “Assemblies” work. This is poorly documented and I didn’t go into a lot of detail in the original post so I’ll try to explain it better.
Rigid Joints and Assemblies
Welds, Snaps, and ManualWelds, Motor6Ds, and WeldConstraints are basically all equivalent to the physics engine. They’re all “rigid joints.” The direction of a rigid joint (which part is Part0 or Part1) doesn’t matter at all, they’re bidirectional. All of these rigid joints combine multiple parts into a single Assembly (with one weird exception that we just changed). No physics forces can separate the parts in an Assembly; an assembly is a single physical object (rigid body).
Welds to Anchored parts…
So we have three different cases with respect to anchored parts:
-
unanchored part welded to unanchored part
-
anchored part welded to anchored part.
-
anchored part welded to unanchored part
Case 1: Unanchored to Unanchored
Nothing changed here. The parts are a single assembly and CFraming one part in an Assembly always moves the whole Assembly (no exceptions!).
When the parts aren’t anchored there’s some sorting rules to determine which part in the Assembly is the root part that I’ve covered before.
Case 2: Anchored to Anchored
Nothing changed here either, but here both parts are two different assemblies.
Anchoring something guarantees it’s an assembly root.
In this case the weld between two anchored parts will even be inactive meaning it’s totally being ignored!
The black parts are both anchored. Notice that the weld is not Active, meaning it has no effect.
Case 3: Anchored to Unanchored
Now case 2 is where something changed.
Previously we had some weird logic that would make any unanchored part directly welded to an anchored part also it’s own “grounded” assembly root (effectively also anchored, physically unmovable, but this “also a root” thing wasn’t recursive).
This meant creating a weld between an anchored part and an unanchored part would “freeze” the unanchored part in place where it was before, without ever applying the weld C0/C1, and not in any way that was reflected consistently by replicated properties. This caused some replication consistency issues where parts would end up frozen in different positions on different clients. It also made the rules for Assembly behavior inconsistent and very hard to explain.
Here’s case 3 in with the old behavior, the way it was before. Red square indicates assembly root. Only the bottom black part is unanchored, note that the unachored part connected to the anchored part is it’s own assembly because of weird logic. Note that the weld between them is not Active. It “grounds” the part, effectively anchoring it, but the weld C0/C1 is ignored. Note how long this paragraph is. It’s not consistent and it’s hard to explain to a new developer who isn’t just used to things being this way even if they don’t understand why.
Now welds to anchored parts aren’t an exceptional. The rules are consistent.
If you want the old behavior you can just anchor both parts. This should get you the exact same behavior we had before.
Here I re-enabled the new logic and anchored the middle part. Note that the weld active and assembly breakdown is the same as the old case before
So from this we have three rules only two simple rules for assemblies:
ContextLost’s Rules of Assemblies
An assembly is a group of Parts connected by rigid joints. An assembly is a single rigid body. If no parts in the assembly are Anchored it can be moved by physical forces.
The First Rule of Assemblies
An assembly is a single physical unit that always moves together. All of the parts within an assembly are positioned relative to the root part, as defined by the Active rigid joints in the Assembly.
It’s not possible to move one part in an assembly without moving all of the others. Everything moves relative to the root. When you assign to the CFrame of any part in an Assembly, the root part is the only part that is actually moved, we just move it relative to the part you wanted to move.
To move the non-root parts within an assembly you have to update the welds that specify how parts are positioned relative to each other (like disabling WeldConstraints to split the assembly, moving the part, and re-enabling the WeldConstraint).
The Second Rule of Assemblies
An anchored parts will always be its own Assembly root. That is part:GetRootPart() == part
is always true if part is Anchored.
If two parts are connected by welds they will always be in the same assembly unless there are multiple anchored parts involved (due to this rule).
The Third Rule of Assemblies
An unanchored object welded directly to an anchored object is it’s own assembly. It will be frozen in place where it was before the weld was created as if the object is anchored itself, except it’s not recursive. It only applies if the part is directly welded to an anchored part. The position of the unanchored part may not replicate consistently.
This “third rule” is what we changed to make the behavior of welds simpler and more consistent for developers in the future.
Hopefully this helps explain why we did this a little better and why you’re seeing the things you’re seeing.