GarageGames / Torque2D

MIT Licensed Open Source version of Torque 2D game engine from GarageGames
MIT License
1.67k stars 1.56k forks source link

Objects sometimes appearing multiple times and/or not being removed from GatherContacts #421

Open Mpskydog opened 5 years ago

Mpskydog commented 5 years ago

I need to do additional testing yet in a clean build of Torque (not a custom project) but when I set an object to gather contacts, then report and monitor those contacts, I noticed that sometimes the .getContactCount() of the object would report contacts when nothing obvious was touching (via debug with OOBB, AABB, and collision shapes).

When I go through and verify the contents of the contact list I sometimes see an object listed twice or more. It almost looks like contact with an object is gathered, then the object is not removed from the list when the contact ends. Bouncing against an object can then put several 'copies' of the object in the list such that even if one of the contacts is later deleted from the scene, its reference sticks. Calling .getContact(index) can then result in an exception being thrown.

EDIT: Changing bodies between static / dynamic / kinematic seems to cause this to happen.

Example: A dynamic body falls to the ground and makes contact with the ground plane. A dynamic body rolls against the now static body and rests in contact with it. The first body is then changed to a static body to prevent it from being moved by the player or being pushed around by other objects. Then later that first body is changed back to dynamic. That seems to increase the likelihood that the original 'contact' is kept perpetually in the contact list after it breaks contact with the ground or other objects)

Mpskydog commented 5 years ago

Looks like I can reproduce it with the default truck toy:

1 Load the truck toy 2 Ensure both wheels of the truck toy are resting on the same object (example, both on the ground) 3 In the console: trucktoy.frontwheel.setgathercontacts(true); trucktoy.rearwheel.setgathercontacts(true); 4 Drive the truck onto another object, such as up the cars, and then back down onto the ground 5 In the console, verify how many/what IDs are in the contact list. Provided they are both resting on the ground plane, it should be one contact each at this point: echo(trucktoy.rearwheel.getcontactcount() SPC trucktoy.frontwheel.getcontactcount()); echo(getword(trucktoy.rearwheel.getcontact(0),0) SPC getword(trucktoy.frontwheel.getcontact(0),0)) 6 Set one wheel to a different body type (Static or Kinematic): trucktoy.rearwheel.setbodytype(static) 7 Have a little fun with the truck toy deforming and doing crazy things with one of its wheels welded in place, then set the body back to dynamic: trucktoy.rearwheel.setbodytype(dynamic) 8 You should now have two contacts listed for one wheel, and one contact listed for the other wheel. Checking those contacts should reveal they are all the same ground object.

Mpskydog commented 5 years ago

Got distracted and accidentally close

greenfire27 commented 5 years ago

I believe when this was set up that the assumption was that objects would not change types once they are created. Obviously, that's not the case. Most likely the code that removes collisions does not do so with Static types. I can't promise a fix in the near future, but I'll look into this at some point. Since you provided steps to reproduce it shouldn't be hard to hunt down.

Mpskydog commented 5 years ago

Sure, I may also play around with it to see if/how I can get around it. Maybe by turning off contact gathering for a time or something else.