How to keep a Rigid Body still while attaching a joint

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By GreasyMcBeef

I’m trying to attach a PinJoint2D at runtime to a RigidBody2D already active in the scene. I can move the rigid body as needed, but my main problem is that I need to make sure the body is completely still between one physics processing step and the next so that the joint attaches at the correct rest position (since the rest position is set after the rigid body is moved by physics).
To make matters more difficult, I already have a second PinJoint2D attached to the rigid body acting on it. Options I’ve tried:

  • Setting the body’s mode to MODE_KINEMATIC for one step

  • The new joint doesn’t actually attach until the mode is changed back to MODE_RIGID

  • Setting the rigid body’s sleeping value to true

  • Behaves similarly to the previous attempt; doesn’t attach the joint until the body is awake again.

  • Setting the rigid body’s custom integrator to true

  • The already-existing joint still pulls on the body, moving it out of place. I also tested with a bias of 0 and softness of 16 on the existing joint, but that still has a pull. This might work if I could just disable the second joint for a step, but I don’t know if that’s an option.

Does anyone have any suggestions on how to keep a rigid body totally still for one physics processing step? Thanks!

have you tried to implement a custome integrator and set every force to zero and overwrite the new position with the current position?

klaas | 2021-07-09 20:03

Yes, I’ve tried setting the custom_integrator property to true with no forces applied in the custom _integrate_forces and then overwriting the position (via global_position since it’s a rigid body), but I can’t seem to set the force of the remaining joint attached to the body to 0 unless I entirely detach it, which I don’t think is a viable option for what I’m trying to do.

GreasyMcBeef | 2021-07-09 21:25

did you now that you have to modify the " PhysicsDirectBodyState" object in the _integrate_forces call to actually alter the physical behaviour of the body?

klaas | 2021-07-09 21:28

I am now, but that still doesn’t stop the remaining joint’s pull on that body, since I think the joint forces are applied after _integrate_forces (possibly applied separately from the node entirely or at least after _integrate_forces, based on what I can tell); I’ve tried setting its angular and linear velocities to 0 in _integrate_forces to see similar results. I don’t see any fields or functions on the Physics2DDirectBodyState that would prevent the remaining joint’s pull other than maybe sleeping, but then we end up not setting the newly established joint…

GreasyMcBeef | 2021-07-09 21:41

so the main problem is to stop the other joint from pulling on the body.

Maybe clamping this joints forces to a tiny value is the way to go …

klaas | 2021-07-09 21:53

I’m using a PinJoint2D (you had linked a PinJoint for 3D), which only has bias and softness available to modify unless I’m missing something. I’ve tried setting the bias to 0 and setting the softness to a very high value (even higher than the 16 in the question where I had tried it there), but there’s still some pull coming from somewhere that I can’t explain.

GreasyMcBeef | 2021-07-10 15:26

Hu, im running out of ideas … only hint i can give is to check out the PhysicsServer. This is the lowest level you can get in godot physics.

klaas | 2021-07-10 18:08

I did see a JOINT_PARAM_MAX_FORCE value on the joint param setup function on the physics server, but setting that to 0 didn’t fix the problem, and just caused strange behavior. However, I also just noticed a pin_joint_create function on the physics server that takes an Vector2 anchor argument; I haven’t tested it yet, but I’m hoping this anchor will actually let me set up a joint at the exact spot I want. Thanks for the help!

GreasyMcBeef | 2021-07-10 19:19

Following up, calling Physics2DServer.pin_joint_create let me create a new joint with the correct resting position via the anchor argument, which is exactly what I needed. If you add this as an answer, I’ll mark it as accepted. Also, do you know how I can access that new joint’s node via its ID? The creation function returns an RID, and I can call get_id on that, but I can’t figure out how to grab the actual node to work with from there.

GreasyMcBeef | 2021-07-10 19:58

I dont think there is any sceneTree node when you create the joint in the physics server directly. Its usually more the other way around, when you create a joint, the joint will create and manage a joint instance on the physics server for you. if you do it your way you have to use the physicsserver methods all the way.

klaas | 2021-07-10 20:06

:bust_in_silhouette: Reply From: GreasyMcBeef

Based on the comment chain above with klaas, I was able to get a working implementation by moving the joint handling for this specific joint to the physics server via calls to Physics2DServer.pin_joint_create and Physics2DServer.free_rid, since pin_joint_create takes an anchor position argument.
Important notes:

  • Even when handling joints in the physics server, you still can’t re-establish a joint in the same physics processing step that you freed it in
  • If re-attaching a joint via the physics server after moving it, be sure to call ForceUpdateTransform if you moved one of the objects before calling pin_joint_create