briansemrau / godot_box2d

A C++ module that integrates the Box2D library with the Godot game engine by providing nodes for standard Box2D objects.
MIT License
44 stars 4 forks source link

Sliding along and off flat faces leaves previous contacts stuck in the contact list. #71

Closed ShadyChibinko closed 3 years ago

ShadyChibinko commented 3 years ago

Godot Version: v3.2.2.stable

Branch: 3.x

Issue Description: Sometimes when you slide the flat face of a shape off another shapes, contacts from that collision remain permanently stuck in the contact list. I say 'sometimes' because there are instances where it doesn't happen. But for the most part it's pretty consistent. The old contacts will continue to build up with each slide off until the limit of contacts_reported has been reached.

See example .gif below _(contactsreported is set to 2): Example

As you can see, normal detachments work as expected. It's only those moving on the axis parallel to collision that have issues. I've only encountered this problem with flat faces (i.e. RectShape, PolygonShape, and flat sides of CapsuleShape). Curved faces are fine (i.e. CircleShape and curved sides of CapsuleShape). Interestingly, get_colliding_bodies() does not suffer and continues to work correctly.

Steps to reproduce: Open the minimal reproduction project, turn on 'Visible Collision Shapes' and run the main scene. WASD moves the left box. Arrow keys move the right one. The labels in the top left corner show the results of get_contact_count() and get_colliding_bodies() for the former. Push the two boxes together so that they're colliding. Then move either along the parallel colliding axis until the faces no longer touch. Do this multiple times.

Minimal reproduction project: Phantom.Contacts.Test.zip

ShadyChibinko commented 3 years ago

Just realized in the gif. The lower label is meant to say get_colliding_bodies().

briansemrau commented 3 years ago

Looks like it may be a bug with the way that contacts from box2d are buffered. Still looking for the exact root of the issue.

briansemrau commented 3 years ago

In the original implementation, I missed a case in which the b2PointState in PreSolve swaps indices (I assumed add/remove are in the same index). This resulted in a previously tracked contact being overwritten, preventing it from ever being removed.

briansemrau commented 3 years ago

Thanks for the bug report :)