How to get contact position when collision happens in physics engine?

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By lizistorm
:warning: Old Version Published before Godot 3 was released.

In my case I want to get the position the ball(RigidBody2D) contact with the wall(StaticBody2D).

Can’t find solution in document and google search. Anyone know how to do this here? Thanks!

I finally found the solution. Use Physics2DDirectBodyState in _integrate_forces callback with RigidBody2D to get the collision position:

func _integrate_forces(state):
    state.get_contact_local_pos(0)

lizistorm | 2016-04-02 00:31

When I try using this, it tells me that this function doesn’t exist, was this function removed in an update or something else?

LaranjoLouco | 2020-10-15 19:30

oh lol, i just copied the code and i forgot to change “pos” to “position”

LaranjoLouco | 2020-10-15 19:32

when i try this, i get this error “E 0:00:01.042 get_contact_local_position: Index p_contact_idx = 0 is out of bounds (body->contact_count = 0).”

LaranjoLouco | 2020-10-15 19:55

Oh, i forgot to set the contacts reported higher than 0

LaranjoLouco | 2020-10-15 21:05

:bust_in_silhouette: Reply From: tiernich

in the ball rigidbody2D check contact monitor in the inspector and set contacts reported > 0.

Now check if the ball hit the wall using: get_collinding_bodies() - its an array so use for to loop and see if hits the wall.

And simply use get_global_pos() for the ball

func _fixed_process(delta):
    for bodie in get_colliding_bodies():
        if bodie == wall:
           get_global_pos()

maybe a better way is to edit the node connections and body_enter() this will trigger only once giving better performance.

I don’t think that is the contact position (point where the two bodies touch), but just the position of the body it collided with.

batmanasb | 2016-03-28 08:44

Thank you for the answer.

Actually I’m using the body_enter signal. But I don’t know how to get the point where the two bodies touch as batmanasb said. I want to instance a effect like particle at this position.

Do you know how to do this?

lizistorm | 2016-03-28 13:44

oh, i see now. one of the things i am struggling is understeand meaning of text(i dont speak english very well) some times i do not get the general idea of the text because read only some words… i will pay more attention to that :slight_smile:

tiernich | 2016-03-28 14:36

ok, well, never try do that, but, do you already try use area2D to see if some functionally fits?

Or maybe getting the direction and angle of the ball you can calculate where hit when hit happen?

maybe even some raycasts?
or small group of area2D covering the object

just throwing some ideas here :))

I will make some research here, if find something i tell you

tiernich | 2016-03-28 14:40

Sorry for my bad English. It’s not my mother language too:)

Well I just thought about sending a raycast when body_enter. But this way maybe less effect. I want to know if there is a build-in way in engine to do this.

I’ll do some research too. Thank you for your help:)

lizistorm | 2016-03-28 14:59

if we enable “Visible Collision Shapes” in the editor, it shows exactly the collision points we need. I think it’s only not exposed to the GDScript object.

timoschwarzer | 2016-04-07 11:11

:bust_in_silhouette: Reply From: zendorf

As far as I can tell there is no builtin function to do this with RigidBody2D, but there is for KinematicBody2D. Not sure what your game is, but can you use a kinematic body for your ball instead?

To get a collision contact point for a kinematic body is very easy. For example:

if is_colliding():
    var collider = get_collider()
    var col_pos = collider.get_collision_pos()

Oh. I’ll try in that way. Thanks!

lizistorm | 2016-03-29 00:12

This way works. And I think the get_collision_pos() API can be exposed to other physics body not just kinematic body.

lizistorm | 2016-03-29 14:42

that would be convenient, true, even one year and half later (for exact same purpose : colliding needs FX!!)

Graphitik | 2017-09-08 23:40

:bust_in_silhouette: Reply From: lukas

What about this? (after you monitored the contact using advice from other answers)

contact point = x - r u,

where

  • u denotes the normal vector of the “wall” plane in direction towards to ball (u has unit length)
  • x denotes the center of ball (position of ball)
  • r denotes the radius of ball

Nice way!

Each wall can keep it normal vector and calc the contact point with the body_enter body.

lizistorm | 2016-03-29 14:38

:bust_in_silhouette: Reply From: voOID

Just as a side note, if you have a KinematicBody2D that “moves and slides” and you want it to push some RigidBody2D body around you can have this method in the KinematicBody2D that applies a directional force at the exact point of impact:

// This is in C#
public override void _PhysicsProcess(float delta)
{
	var movementSpeed = 100f;
	var pushFactor = 50f;

	for (int i = 0; i < GetSlideCount(); i++)
	{
		var collision = GetSlideCollision(i);

		if (collision.Collider is RigidBody2D collider)
		{
			var localCollisionPos = collision.Position - collider.Position;

			collider.ApplyImpulse(
					localCollisionPos,
					-collision.Normal * movementSpeed * pushFactor);
		}
	}
}

For this to work you need to have the infiniteInertia parameter of MoveAndSlide() to be false though.