How to add custom 2D physics interactions between two rigidbodies?

JoelJoel Posts: 2Member
in 2D

What I need

Some way to write a custom 2D physics interactions between two rigidbodies such as a custom Joint2D or an extension to PhysicsServer2D.

I think extending PhysicsServer2D to include a custom function that handles the interaction maybe the way to go (as this seems to be where the joint2D code is) but I'm not really sure how to extend this nor how to make Godot use the extended version.
Most of the resources I have found just say use integrate_forces (not powerful enough for this) or us Physics Servers but they don't say how to use the physics server.

Background

My Goal

To have two rigidbodies 'tied together' such that when they get to far apart their velocities synchronise preventing them getting further away from each other (as if there was a rope between them).

Solutions that do not apply

  • Using many rigid-bodies pin joined together to simulate a rope. This would be a very inefficient solution introducing a lot of new rigidbodies unnecessarily.
  • Solutions for KinematicBodies, these do not apply as I am building a physics based game. I may fallback on KinematicBodies but it would require me to rewrite a lot of physics code which I would prefer not to do unless it is my only option.

Solutions I have already tried

  • Using a DampenedSpringJoint2D, this join does both compression and stretching forces whereas only stretching forces are needed, the spring also just bounces back instead of synchronising.
  • Using a GrooveJoint2D, this does not allow for movement outside of the axis and does not enforce a maximum length properly.
  • Custom _integrate_forces on both bodies. This is very close to working, it works if one body is static however, as I cannot access the physics state of both objects the objects cannot be synchronised as each object is working with an outdated information from the other object.

Tags :

Answers

  • vinpogovinpogo Posts: 47Member

    just an idea i would try out.

    Assumption made:
    One of the rigidbodies is controlled (== first) and the other (== second) follows, otherwise you wouldnt know which rigidBody needs to syncronize.

    • have the common parent check wether the distance is above your threshhold
    • when it exceeds the threshhold, get the linear_velocity from the first rigidBody and pass it down to the second one. If the distance is below, then pass down null.
    • in the integrate_forces of your second body then read the set variable and set your linear_velocity if it is not null

    I think this should work fine. Let me know

  • JoelJoel Posts: 2Member

    Thank you for your answer

    The answer is not quite complete as the velocity of both objects needs to change from the interaction and linear velocity is only available on the Physics2DDirectBodyState which I thought was only available from integrate_forces, however, it did lead me to a satisfactory solution.

    The Physics2DDirectBodyState for a any body using Physics2DServer.body_get_direct_state(rid)
    This has two caveats:
    1) there is only one Physics2DDirectBodyState that gets updated when this is called
    2) the Physics2DDirectBodyState can only be modified after the first custom integrator is called but before the body's own custom integrator is finished.

    This means that in order to create a custom force interaction between two bodies the first body to have integrate_forces called must calculate and update the velocity of both bodies using Physics2DServer.body_get_direct_state(rid)

    This solution still has one flaw: any force that occurs between the first body's integrator and the second body's integrator will only effect the second body. I do not think there is any way of solving that.

Leave a Comment

BoldItalicStrikethroughOrdered listUnordered list
Emoji
Image
Align leftAlign centerAlign rightToggle HTML viewToggle full pageToggle lights
Drop image/file