How to Make DistanceJoint2D Stabilize Quicker?

Hi all!

I’m having a problem with DistanceJoint2D accuracy and stabilization. I’ve attached an image of my game where I’ve stripped most of the unnecessary stuff out, and left the box collider (box with green outlines) of the player character (which has a Rigidbody2D) and the DistanceJoint2D (green line).

The left side of the image (1) is how the game looks the very next frame after the Distance Joint has been enabled. As you can see, the anchor point (the blue circle on the green line) is not at the correct distance, as it should be at the end of the green line, like it is on the right side (2).

Depending on the situation, it usually takes 1 to 5 frames to reach situation 2 from the joint creation (1). The “Distance” variable of the DistanceJoint has the same value in both frames, though, so I suppose that’s the distance the joint is aiming to keep, but requires a few frames to get there.

1-2 frames of slight movement wouldn’t likely prove to be a problem, but 5 will start to be noticeable, and I’d like the stabilization rate be as consistent as possible so that I could get fairly predictable results.

I have tried increasing the velocity and position iterations of the Physics2D settings, but they don’t really seem to help. Some big values actually seem to make the problem even worse, and there’s a lot more movement before the joint stabilizes.

Could someone point me to the right direction on what ideas I could try to make this more consistent? I also don’t have detailed knowledge about Baumgarte scales and most of the other Physics2D settings, so while I’ve tried different values with all of them, I’m not really sure what I should be tweaking and to what direction. So, any help with these would be appreciated as well!

This is the Box2D b2DistanceJoint (v2.4.0) as seen here although if you have the “Max Distance Only” setting selected, we switch to using the b2RopeJoint as seen here.

For the b2DistanceJoint we create this with full damping (zero spring) and a stiffness of 0 (rigid) so it’s about as reactive as it gets. My only observation is that you mention frames which I presume you mean simulation steps (FixedUpdate) and not render frames because they are obviously not the same unless you’re running physics per-frame.

You mention accuracy; I have never seen accuracy issues so maybe you’re just throwing that word out there.

FYI: Baumgarte is used when solving overlaps and isn’t related to joints.

Thanks for the quick reply!

Okay, so am I right to assume that the only way to try to get the stabilization quicker is by adjusting the Physics2D values? What variables should I be looking at, other than Velocity and Position iterations?

Yes, you’re right, I should’ve made a distinction between the two. I paused the player window and moved forward step by step with the editor button, so I presume this forwards the time to the next rendered frame. But even though I was referring to the stabilization taking 1-5 rendered frames, I feel that the number of fixed steps the joint takes to stabilize is not consistent either. So, for a short period of time (during the stabilization), the joint behavior both feels and looks inconsistent.

By accuracy, I meant that the distance between the anchor point and the connectedAnchor point is not instantly what I set it to be via the distance variable of the joint. For example, if I set this distance to 4, it may initially start at 3.7 before stabilizing to that 4 after those 1-5 render frames. So while it’s accurate after those few frames, it isn’t that way right after I enable or create the joint.

Okay, this is good to know! I’ll stop looking at those variables, then.

There are no global settings to change for it. All Box2D joints are soft joints which make for a much more stable simulation because they work over time. Instantly changing a constraint perfectly causes all sorts of problems if whatever is connected is in contact with other things.

It’s not clear how you’re using this too. At first I was wondering if you were talking about it moving from the authored position then hitting play or if you were just changing the distance dynamically in the game. I was curious to know if a different joint would be more appropriate for you that might give you better results.

There’s nothing in Unity that controls the behaviour of the joint though. With joints, iterations improves their accuracy but that’s it.

Okay, this seems to confirm what I seem to have read elsewhere, that you’ll just have to live with the constraints. My game will not be that physics-heavy and realistic physics aren’t required, since there’s only some basic rigidbody simulation going on otherwise, so I’ll probably try to create a custom “distance joint” that doesn’t perfectly obey the physics engine calculations, but stabilizes the way I want it to.

Both images are screenshots taken from the actual gameplay, and I have a rope/wire script that sets the distance variable of the joint at the same time the joint is enabled. So, I’m not manually altering anything via the scene editor window.

1 Like

The thing is, you’re hinting that this isn’t realistic however even if it takes 5 simulation steps to get to the constrained position, that’s still only 100ms or so moving even a considerable distance. Even a few steps in it likely has gotten most of the way so I’m more curious to see what it is you’d like here; it seems you want it to match the constraint in 1/50th or even 2/50th of a second which is fast and TBH, just sounds like you want a hard constraint which isn’t unreasonable, just not how most impulse-based physics joints works due to issues like overshoot.

For a custom one then, I presume you want to instantly calculate the constraint more along the lines of a Verlet-based constraint? If so then I’d recommend calculating that distance/rotation and using Rigidbody2D.MovePosition and MoveRotation which works well even on a Dynamic body-type (at least for 2D Physics it does). That way it’ll continuously to interact with the surrounding scene.

Yeah, I understood that while physics simulations are incredibly handy in some situations, they do occasionally require a few iterations to get everything right. If you imagine Spiderman swinging with the web shooter (the web being the DistanceJoint), you can probably picture how even 100 ms would hinder the natural momentum transfer between the swings. That’s what’s causing the problem in my game.

This is exactly what I have begun doing! With some trigonometry and the RB2D functions you mentioned, I think I will get a solution that suits my needs.

Thanks for your help!

1 Like