The Godot Q&A is currently undergoing maintenance!

Your ability to ask and answer questions is temporarily disabled. You can browse existing threads in read-only mode.

We are working on bringing this community platform back to its full functionality, stay tuned for updates.

godotengine.org | Twitter

+2 votes

I have two RigidBody2D (and maybe there are more PhysicsBody2D around) that I want to:

  1. Check if they have collided.
  2. Know the collision velocity at contact point of each body.
  3. Based on both velocities (magnitude and direction) compared to the normal vector of collision, decide which body hit the other body.

I can use _integrate_forces(Physics2DDirectBodyState state ) and reading the state I can know the list of colliders (get_colliding_bodies), the collision contact position for each one of the colliders (state.get_contact_collider_pos), and the velocity of the body at the contact point (state.get_contact_collider_velocity_at_pos).

I even could now the Object of one of the colliders (state.get_contact_collider_object). Even I can imagine that I detect the object in the list of colliders and it is the other body that I want to check its velocity.

How can I know the velocity on contact point of the other collider? I guess I can't directly call _integrate_forces so once I have detected the collider I'm interested in, how can I know its velocity at the colliding point?

in Engine by (659 points)

3 Answers

+1 vote

Using a test_motion() would result in a Physics2DTestMotionResult which may have what you want. See here.

by (1,118 points)
+1 vote

use a var called velocitylastframe or something like that
at the end of fixedprocess() set velocitylastframe = getlinearvelocity()
When 2 physics bodies collide their velocities are changed in the frame in which they collide, before any fixedprocess() runs, so using getlinearvelocity() when a collision happens will return the new, post-collision velocities. But if you always have the velocity from the last frame, you will have the velocities from right before the collision.

by (16 points)
+1 vote

To anyone from the future who is looking for how to designate a "hitter" and "hittee" and find the collision force after a collision as I was, here is the code that does that.

Firstly, in the physics process or integrate physics (Whichever you use) paste the following code:

previous_velocity = current_velocity
current_velocity = self.linear_velocity

Next, go to the physics object's node and access its signals. Connect the node's onbody_entered signal to itself, and find the newly made function in its script, and set it to this:

func _on_Object_body_entered(body):
var hit_force = 0
var hitter = false
if body is RigidBody2D:
    if body.get_index()>self.get_index():
        if body.previous_velocity == Vector2.ZERO:
            hitter = true
            hit_force = self.previous_velocity.length()*body.mass
        elif self.previous_velocity == Vector2.ZERO:
            hitter = false
            hit_force = body.previous_velocity.length()*body.mass
        else:
            var hit_velocity = (body.previous_velocity - self.previous_velocity.project(body.previous_velocity)).length()
            var enemy_hit_priority
            var our_hit_priority
            var collision_angle = abs(sin(previous_velocity.angle_to(body.previous_velocity)*0.5))
            if collision_angle == 0:
                enemy_hit_priority = body.previous_velocity.length()
                our_hit_priority = self.previous_velocity.length()
            else:
                enemy_hit_priority = body.previous_velocity.length()*(body.mass*collision_angle)
                our_hit_priority = self.previous_velocity.length()*(self.mass*collision_angle)
            if enemy_hit_priority > our_hit_priority:
                hitter = false
            else:
                hitter = true
            hit_force = hit_velocity*body.mass
        on_hit(hit_force,hitter)
        body.on_hit(hit_force,not hitter)

Now just make the on_hit(hit_force, is_hitter) function referenced in the code and you're done!

Is it gross? Sure. Is it uncommented because I'm lazy? Yup. Does it work after DAYS OF SEARCHING? Certainly.

by (16 points)
Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read Frequently asked questions and How to use this Q&A? before posting your first questions.
Social login is currently unavailable. If you've previously logged in with a Facebook or GitHub account, use the I forgot my password link in the login box to set a password for your account. If you still can't access your account, send an email to [email protected] with your username.