So currently when you make a Manual weld and update C0 OR C1 it will pick an arbitrary part to stay still and will move the other part. Now, internally this logic is not arbitrary. ROBLOX has an internal notion called a “Root Part” which is decided by a set of criteria (Size, if it’s anchored, welded to something anchored, and so on). I’ve heard users complain about the fact that it’s unpredictable since users don’t have access to the concept of Root Part.
The reason I’m posting here is because I’ve figured out a way to modify the behavior without having to change internals or the reliance on Root Part, but I was wondering if this would break anyone’s behavior, and if a different behavior is more desired?
My questions are:
If I modified the code so that changing Weld CFrame would move Part1
around Part0 (keeping Part0 static) would this break any of your
Would this be the preferable setting?
Do you expect Part0 to remain static, or do you expect modifying C0
to move Part0 and modifying C1 to move Part1?
Yes – Part1 moving around Part0 should be the behavior for all joints. This is what these properties are for and arbitrarily choosing a part to be Part0 other than the specified one is not so great design. Thank you for fixing this.
Part0 should always be static. Welds should not be two-way – that just over-complicates them. If I want PartA to be 1 stud up from PartB, I would set PartB as the Part0 and use the weld to move PartA, the Part1, up one stud – not set the one I want to move to be Part0, the root part.
Quick update: So it looks like there isn’t a good way to solve this without changing how ROBLOX generates internal tree structures. The way that I was going to try and sovle this would require a lot of hacking, and the proper fix would require a bit of a time investment. I think I’m going to back off on this until early next year where we will want to refactor the way that we generate our Tree structures to work correctly with joints, which will be the correct way to fix this problem.
So Echo, there is a reason this bug has been in ROBLOX for a looong time… Hang in there guys.
Khanovich, would you be willing to explain how ROBLOX generates tree structures internally? I’m asking because right now I’m trying to determine if a deep weld structure is prohibitively more expensive than a shallow weld structure.
If a deep weld structure is relatively equal in cost, especially in terms of C0/C1 updating for animation purposes, then I’ll be able to allow players to build pivoting components in my game without significant performance costs.
Edit Another question is if it’s prohibitively expensive to update the C0/C1 coordinates frames, and what sort of restructuring goes on when I do that.
In general updating weld C0/C1 for animation purposes is an anti-pattern. Off the top of my head rendering engine will be forced to recompute a bunch of state - a LOT of state for complicated models - on any change like that because it assumes that welds represent rigid connections and optimizes based on that.
Good point. In that case this update should also affect Motor6Ds for use in animation. My problem with the current behavior is that you can’t easily animate a part that’s larger than the part it’s connected to, and making C1 always move would fix that.
Yeah, we discussed fixing this for motors with @Khanovich as well and it has the same issues where the motor update is tied to the tree structure, the difference being that rendering engine handles motors as animatable joints and welds as rigid joints.
Current thoughts are that hacking around the tree structure is dangerous and we should try to enforce the direction of joint edges while building the tree. To answer @Quenty’s question somewhat, imagine a graph where parts are vertices and joints (surface joints, manual welds, motors, etc.) are edges. We currently have an algorithm that finds the spanning tree of this graph ( https://en.wikipedia.org/wiki/Spanning_tree ) using some heuristics that in general make sure that the larger parts volume is, the closer it is to the root of the tree.
Once a tree has been established, we store transforms of all parts as a delta to the parent. Whenever you change a coordinate frame we have to update the subtree of that node, so the question of update efficiency wrt physics depends on the specific structure and specific node being updated.
Plus we have some gross hacks that maximize the probability of the humanoid root part becoming root.
To solve the problem discussed above you can imagine changing the algorithm to use P0-P1 as a directional edge and find a spanning tree of that DAG (and break cycles somehow if it’s not a DAG).