Changes to Surface-Based Welds and Part Property Setters


#1

Roblox has been growing and evolving as a platform for 12 years, and it’s only natural that some things that made perfect sense for Roblox 12 years ago might not make sense now.

Our surface-based building system used to be a hallmark of the platform. Today, we have better alternatives for building. The behavior of the surface based building system often confuses new users and is avoided by most experienced builders.

We are planning to make some changes to make the behavior of these surface based joints less confusing, and more consistent with our newer constraints as we move towards deprecating and de-emphasizing the use of surface types in the future.

We don’t expect this to break any games, but we still recommend opting-in early and testing your games now!

Why we’re Changing this

Historically, when you place studs and inlets together in Studio and start the game, we run something like Workspace:MakeJoints every time. This tests every part in the workspace for surface proximity and surface compatibility with nearby parts and creates JointInstance joints corresponding to the surface type, like Weld, Snap, Glue or Rotate. These joints are added to JointsService, a hidden service, who’s children are replicated but not saved in the place file. Every time we load the place we need to do this all over again.

This also means the “Join” setting for drag tools in Studio can be misleading. Even if the join setting was set to “Never” while you were building, those joints may still be created when you start the game.

Also, changing the Position, Rotation, Orientation, and Scale properties of a part will break any of these joints connected to the part—and possibly create new ones. Any joints it creates will also be hidden in JointsService. When we investigated use of this property, we found that the games creating joints this way were mostly doing it by accident. Where joints were intended, MakeJoints was also called. Nobody seemed to be able to rely on this actually working.

We’ve opted to make some changes to the behavior of these joints so it’s more consistent and explicit. This way these joints won’t pop up by surprise—and if they do, they will be simple to understand. No secrets, no magic involved. No need to learn new concepts just so you can successfully avoid them.

What’s Changing

image

We’ve added a new Workspace property: AutoJointsMode, accessible in Studio. There are 3 options available:

  • Default: Use the current default value. Currently Explicit as of January 7th. Used to mean Legacy.
  • Explicit: The new mode. This gives you an opportunity to opt in early and test your game now.
  • LegacyImplicit: The old mode. This is a temporary opt-out to buy you more time to report issues and fix your games.

Here’s a video demonstrating some of these changes. I made JointsService visible for demonstration. It’s normally hidden.

When you opt in with Explicit mode:

  • All hidden joints in your place will be moved into Workspace as children of one of their parts, similar to ManualWelds.

    • This is reversible. Changing back to LegacyImplicit will move joints created this way out of Workspace.
  • These joints will now be saved in the place file, so you get consistent results when starting the game.

  • The Studio drag tools will continue to create joints, if Join is enabled.

    • Additional joints created with drag tools will appear in the explorer under their parts, similar to ManualWelds.
    • If Never is selected, no joints will be created. When running, the game parts will not be joined.
  • Workspace:MakeJoints will not run when a game is loaded. What you see is what you get.

    • This can also make server start slightly faster for Explicit mode places with many parts in Workspace.
  • BasePart property setters will no longer implicitly BreakJoints or MakeJoints. The respective C0/C1 CFrame of any JointInstance joints will be updated to allow the part to move, similar to WeldConstraints.

    • BasePart.Position
    • BasePart.Rotation
    • BasePart.Orientation
    • BasePart.Size
    • BasePart.Shape
    • BasePart.___SurfaceType
  • These BasePart property setters will no longer perform a “safe move” and will not attempt to position the part so it does not intersect other parts.

    • Model:MoveTo can be used if you want this.
  • The following methods will continue to make or break joints as before. New joints will be added as children of the part(s).

    • BasePart:BreakJoints
    • BasePart:MakeJoints
    • Model:BreakJoints
    • Model:MakeJoints
    • Model:MoveTo (also continues to do a “safe move”)
  • JointInstance joints will no longer remove themselves if one of their parts is removed from Workspace

    • This allows you to move models in and out of workspace without welds disappearing.
    • This was needed in the past to clean up hidden JointsService joints, but is not needed when they are children of parts.
  • Duplicate rigid joints and kinematic Motor joints will no longer be automatically removed.

One significant change is that these formerly “implicit” joints will now be cloned with a Model because the Model will contain these joints as children.

We are now adding some metadata to model files. Models that are created in an Explicit mode workspace will not automatically call MakeJoints when imported in an Explicit mode workspace. Models made in this mode will have joints saved inside the model. Joints that do not exist in the model will not be added, even if there are compatible surfaces.

JointsService and JointInstances (except Motor6D) are considered deprecated. In general we recommend using WeldConstraints and Constraints in place of JointInstances, with the exception of Motor6D for animation.

When is This Going Into Effect?

Now! You can change the AutoJointsMode property on Workspace to “Explicit” in Studio right now to opt-in your places now and test it. You can also select “LegacyImplicit” to opt out until we force this globally.

As of January 7th, If you have taken no action or AutoJointsMode is still set to Default, then the new Explicit mode will be used when you load the place in Studio or when a server starts. You can still select LegacyImplicit to temporarily opt out at this time.

On Febuary 4th, we will force Explicit everywhere. The LegacyImplicit option to opt out will be disabled and the AutoJointsMode property will be hidden in Studio. Old places will be converted when loaded in studio or during server startup.

We may adjust this schedule if we run into bugs or unforeseen issues in games. Please report any issues you run into!

What You Should Test

We expect these changes to be backwards compatible with most games.

One significant change is that joints will now be cloned with their parts. If your game somehow relies on models cloned from Workspace to not contain any surface-based joints, you may encounter some issues.

You may also encounter issues if your game looks for joints under JointsService that it did not explicitly add there itself. We don’t expect this is common.


We No Longer Automatically Remove Duplicate Welds (In Workspace.AutoJointsMode = Explicit)
How do I turn of "Part-to-part strong joint?"
August Recap: Last Month in the Developer Community
Changing the Behavior of Welds to Anchored Parts
Moving to Workspace.AutoJointsMode = Explicit by Default in January, Forced in Febuary
Destroying weld Part0/1 causes erroneous random welds to other parts + can crash test server
Changing the Behavior of Welds to Anchored Parts
WeldConstraints acting weird when used on a player
Latest Physics changes broke Prison Royale
#2

And so it begins…


#3

Awesome. I haven’t used surface-based connections since 2009.

I hope to see the ability to treat a ‘model’ as a single physical unit without creating welds someday too (like Unity)


#4

Are there any plans to replace Motor6D?


#5

Only early, nascent plans. We know we want to replace it, and that for the use case of animation it should probably be Attachment based. We’re undecided on other design considerations for it, and it’s not at the top of our priority list right now.

TL;DR: Yes, but nothing for sure or that will happen any time soon.


#6

If possible, I think you should setup a thread to see what are the main necessities and constraints developers face when creating animations.

As for an example, in my particular case I find it too difficult to sync native Roblox animations to object interactions, such as picking up and object or making sure your hands are placed correctly in relation to an object you are holding.


#7

Rescheduling changing Default to mean Explicit until after I can ship a fix for an issue with tools dropping when switching tools rapidly.


#8

Reminder that we’re planning to change Default to mean Explicit mode on Monday Update: Postponed. You can still opt out by selecting Legacy a this point but we’re planning to force everyone over to Explicit in mid-November.

We recommend updating your games to Explicit mode now and reporting any issues you run into.


#9

Can we get a guarantee that this will be enabled first?


#10

That change was already enabled this week. Let me know if you’re still seeing issues.


#11

I just enabled Explicit on my game and I’m seeing something I have no idea how to even approach fixing. It’s 2:30 am though so troubleshooting this right now is going to have to wait for tomorrow.


https://gfycat.com/SingleVengefulHog
https://gfycat.com/FewCheerfulHog
https://gfycat.com/UglyCalculatingBrahmanbull

Okay apparently this is picking up loose objects as well (note the egg).

image

Reproducing this was only reliable after around 4 people joined the game, and I can’t seem to make it happen in studio.


Destroying weld Part0/1 causes erroneous random welds to other parts + can crash test server
#12

This looks like a bug that has existed on Roblox since at least 2010. JointInstances without a Part0 or Part1 will sometimes attach to characters at random. I saw this around 2010 with an old weld script inexplicably attaching players to cars and players to players. I saw it recently with JointInstances in the character that had a nil Part0 or Part1 which caused it to attach to other characters or random parts of the world.

I haven’t submitted a bug report because this bug is hard to reproduce and I can’t get a solid repro down. It’s the sort of bug where the natural response is, “no, that can’t be right, something must be wrong with your code” rather than accepting it as an engine bug. I’ve seen it happen multiple times and did a thorough investigation using new APIs recently and found that parts should not have been connected but were. The only similarity between all cases is JointInstances with nil Part0 or Part, and removing those fixes the issue and disconnects the parts that should not be connected.


Related: There’s another “that’s impossible, it must be your code” bug I’ve found recently where the client DataModel gets desync’d from the server. I plan on reporting it but unfortunately can’t give a very solid repro. It happens in approximately 3/10 tests (or less) and only on large games with operations that happen at the start of the game and only for new players. I’ve seen this twice so far, done a thorough investigation each time, and there’s no way that it’s a bug in our code and not a Roblox engine bug. It happens both in live games and in test servers.


Destroying weld Part0/1 causes erroneous random welds to other parts + can crash test server
#13

That is bizarre.

I’m using welds to connect the hitbox part to the character when they start an attack. It turns out the welds are left behind missing their Part0 after an attack finishes. This is definitely the same bug you’ve described.


I’ve also managed to reproduce it in studio. I needed to do some attacks before I could get it to happen. In this particular case the effect appears different between clients. It’s worth noting that in none of the client views, nor the server view do the welds have a Part0 set.


#14

Please see this bug thread for repro.


#15

Thanks for putting together a repro for this. I know @Khanovich tried to fix this a couple times before.

We’ll talk about it more Monday morning, but we’ll probably postpone switching to Explicit by default since it does exacerbate this by not removing welds when the part leaves Workspace, and we need to fix this bug.

We are going to keep the behavior of welds no longer self-destructing when parts are removed from Workspace. That behavior causes a number of problems when moving models between containers and causes issues with replication. You should still update your games to make you clean those up more explicitly or by parenting them to the part that will be removed.


#16

I’m currently testing my game with the attack hitboxes that get destroyed having their welds contained within, but it still appears to happen, albeit less often. Destroy() is always and only called on the hitbox part and variables holding the weld instance are out of scope.
My client ends up desynced with the server after a while, also I can’t jump afterwards?

No idea what’s going on. Surprised other people haven’t posted about this issue in this thread since it’s being a pretty big problem for me.

https://gfycat.com/InexperiencedAllBrownbutterfly


#17

The issues with welds crashing or connecting to other parts randomly should be fixed now, so it should be a good time to try Explicit mode again if you’ve ran into this issue or just haven’t before.


#18

We’ve updated the release schedule, please see the original post.

Starting January 7th we will move forward with Explicit mode being the default for all new and existing places that have not explicitly opted out.

On February 4th all new and existing places will be forced to Explicit mode even if they had opted out before.

Please test and switch your places to Explicit mode now to avoid any interruption. Report any issues you encounter today!


#19

I currently have a script which would change the Surface Type of a part (mainly to stop a wheel from rotating by changing the hinge - using VehicleSeat controller). This has currently stopped working due to this update, was just wondering, would using :MakeJoints() after any change like this fix this issue?


#20

It should. The old property setters included the equivilent of calling BreakJoints before changing the value and MakeJoints after.

Adding these calls yourself, explicitly, should get that same behavior as before. We think it’s better to be explicit about this if it’s what you want.