+7 votes

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!

in Engine by (24 points)

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

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

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

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

when i try this, i get this error "E 0:00:01.042 getcontactlocalposition: Index pcontactidx = 0 is out of bounds (body->contactcount = 0)."

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

4 Answers

–2 votes

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.

by (425 points)
edited by

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.

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?

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 :)

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

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:)

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.

+2 votes

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()
by (268 points)

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

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

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

+1 vote

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
by (672 points)

Nice way!

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

0 votes

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.

by (18 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 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 webmaster@godotengine.org with your username.