onTrigger callback called with the wrong PxActor::userData [phsyX 3.3.4]

[physX3.3.4]
I just witnessed a wrong userData used in the onTrigger callback in a very specific case.
It seems like it’s due to phsyX recycling the PxActor.

Here is what I witness.

Frame N, updating my engine
Due to the logic in my scene, some rigid bodies are removed from the scene thanks to PxScene::removeAggregate and PxAggregate::release
The actor has a userData set to 2 in my case (I use the userData as an index rather than a pointer, but it would be exactly the same issue if it was a pointer)

Frame N, updating physX
AS the rigid body actually was in collision and had a trigger shape, the corresponding collision pair is flagged to fire the next callback.

Frame N+1, updating my engine
Due to logic in my scene again, I create and add a new rigid body in the scene thanks to PxAggregate::addActor and PxScene::addAggregate
The user data is set to 3 for this new rigid body.

Frame N+1, updating physX
As a collision pair was previously flagged to fire callback, it does fire my onTrigger callback with a eNOTIFY_TOUCH_LOST pair.
But when looking at triggerActor in the pair, it has a userData of 3 (the new rigid body), instead of 2 (the one that was deleted)

Looking further into this problem, I realized that the PxTriggerPair::triggerActor was actually the same pointer when I was first notified of the eNOTIFY_TOUCH_FOUND of my rigid body 2 (before frame N). So I just guess that PhysX is recycling the PxActor before firing the onTrigger callback, which brings me to this wrongly reported eNOTIFY_TOUCH_LOST pair.

Dunno yet if the same thing happen with phsyX3.4, I’ll give it a try…

What are the flags on the triggerPair? If the flags are set as eREMOVED_SHAPE_TRIGGER or eREMOVED_SHAPE_OTHER, that tells you that one of the shapes (either trigger or the other shape) was removed.

In this case, a touch lost is still emitted because you might still need it (e.g. if you were keeping track of the number of shapes inside a trigger). However, the pointer to the shape or actor is potentially pointing to memory that may have been released or recycled if you not only removed the shape or actor from the scene, but also released it. You have to think about how to handle this inside your logic - whether that means deciding not to dereference pointers when the shape is reported as having been removed, or removing actors from the scene and releasing the actor after fetchResults has finished.

Hope this helps.

Hi Kier,

Thanks for the clarification. The flag is effectively set to eREMOVED_SHAPE_TRIGGER or eREMOVED_SHAPE_OTHER in my case, and I was just missing it.
I’m now able to fix this correctly thanks to your explanation.

Cheers,
Yann.