Collision trigger events are sometimes delayed

Long story short, I’m working on a project where the user can move a sphere with the mouse over a plane. At certain areas on this plane, the user needs to be warned that that area is a bad location to place the item they are moving. (There’s a video of this at the bottom of this post).

To achieve this I’ve tried using the ammo physics engine where I create a trigger volume on the areas that are “bad”, and I’ve added a collision component as a sphere with a Kinematic rigid body.

The issue I run into is that the trigger events are sometimes delayed. I’m unable to replicate exactly what is causing this. But I’m sometimes able to move the sphere outside of the bad area without the “ontriggerleave” event triggering instantly.

I’ve created a simple project replicating this:

Where I have a box as my triggervolume and a sphere that is constantly moving in and out of the trigger volume. As soon as the sphere enters the trigger volume I swap the material on the box.
As you can see in the project, the material update is sometimes instantaneous, and sometimes it’s delayed quite a bit.

I’ve also made sure that it’s not the actual material change that is slow, as I’m still able to see this error just by logging the “ontriggerleave” event when I manually move my object without doing any material updates.

Here’s a video from the test project showing that the material update is sometimes delayed and sometimes not:

Here’s a video from my actual project where you can see the actual usecase. The first couple of times it works fine, but in my last attempt, I’m able to move my “sphere” outside of the area and the triggerleave doesn’t happen until 2 seconds after I’m outside it.

So my question is:
Looking at how I’ve setup my physics bodies in the test project. Is it something I’ve misunderstood or implemented in a weird way?
Is there any adjustments I can make to fix this delay?
Or do I just have to live with this as these are limitations on the phyiscs enginge?

Worth noting is that I’ve tried using both types of events. Collision events from the sphere, and Trigger events from the box. Both have the same result. It’s usually the “oncollisionend/ontriggerleave” events that are delayed.

I guess an alternative would be for me to write these methods myself as I don’t really need most of the physics, such as gravity and friction etc. etc.
I literally only need to calculate wether or not two primitive objects occupy the same area. But it would be nice to be able to utilize Ammo in case the requirements change in the future.

Without debugging it is hard to say what is causing the delay.

If you have an opportunity not to use a physics engine, then you should take it. Ammo will reserve 64 Mb of memory immediately on load, no matter how many rigidbodies you create or how you use it.

For your case, the engine has a bounding box that can test intersection with a sphere. That should be enough to test a collision that you demonstrated:

I didn’t mention it initially but the next step to this feature will be to detect if the sphere is located on the object or not.
There will be objects with holes in the center in weird shapes such as this one:

And there is a multitude of objects like this one which will be much harder to account for using only the bounding box, unless I write the methods for mesh collisions myself.

It’s a desktop application so using 64mb of memory shouldn’t be a problem. (other than a slight increase in the initial load time).
The rest of the application isn’t very graphics heavy.

For that reason I’d really like to be able to use Ammo for this.

1 Like

I see, yeah, in that case, having Ammo should help. I will take a look at your repro today or tomorrow, once I have some spare time. No promises that I find a solution, though :slight_smile:

1 Like

I’ve looked into it a bit. So, its one of those unfortunate downsides of using a rigidbody as a trigger. Basically, Ammo is calculating the contact data in the dynamics world and depenetrate objects by pushing them outwards. For efficiency, it caches the contact points in a persistent manifold cache. Since PlayCanvas is using a rigidbody instead of ghost objects, Ammo calculates all the contact info for triggers as it would for normal bodies, caching the contacts. That cache can live pretty long, giving you long living contacts that you experience.

So, first option is that you clear the persistent manifold cache, if one of the two objects in the contact manifold is a trigger. Clearing a manifold cache is not exposed to Ammo, unfortunately, so you would have to create a custom Ammo build to do that.

Another option would be to set a contact breaking threshold on the persistent manifold. This will auto remove a contact from the cache, if the bodies are further apart than given threshold value. This is also not exposed in Ammo, unfortunately, and you’d have to create a custom Ammo build as well :frowning:

If you do go for custom build, then clearing the manifold cache should be the preferred one for your case probably, as you don’t have dynamic simulations.

Another option is to use a ghost object, instead of a rigidbody with bitmask as a trigger. This will avoid contact manifold alltogether and won’t have that issue. The good news is that the current Ammo version supports ghost objects, and you don’t need to build a custom version. The bad news is that PlayCanvas doesn’t use them, so you would have to implement them yourself, using Ammo API directly.

None of the options are easy to approach, I’m afraid. I’m working on a Jolt physics integration with PlayCanvas, which will be released soon. So, perhaps you could switch to that once its out.

1 Like

Really appreciate you digging into this!
I’ll try your solutions and see what works best.