- Home /
OnTriggerEnter/OnTriggerExit called multiple times with MeshColliders
I used to have a big scene with some pots (Mesh Colliders) moving on a conveyor with sensors (Box Colliders). Everything worked as expected but we had to change the all scene and scale the measurement unit to its 10th. After that, my Mesh Colliders (the pots) triggers OnTriggerEnter
and OnTriggerExit
multiple times when it's going through the Box Colliders (sensors) even if a pot's collider is completely enveloped by the collider of the sensors.
I tried to look for information but all I can find are not-up-to-date problematics, no solutions.
I also tried a way around by verifying if the sensor had already detected the pot concerned after an OnTriggerEnter
is called and by checking if the bounding boxes of the two colliders (pot and sensor) are intersecting after an OnTriggerExit
is called. The latter doesn't seem to work everytime because sometime, when the last OnTriggerExit
is being called, the bounding boxes of the pot and the sensor are still intersecting, thus the script considers the pot is still being detected by the sensor.
Replacing the Mesh Collider Component of the pot with a Box Collider make the sensors react expectedly but I really need a "Cylinder Collider" as a shape for my pots colliders to make the application works correctly.
I found another way around which permitted me to make it work :
Pots have now 2 colliders : - $$anonymous$$eshCollider
for physics - BoxCollider
for sensors
The BoxCollider
triggers the sensors events but are not physically interacting with anything.
A mesh collider may have one or many points of contacts. For instance, when a sphere enters another sphere, you could have 4 contact points since the engine requires a $$anonymous$$imum penetration to valid collision. You can set that value to be smaller but that won't fix your issue. The simplest way would be to have a sentinel boolean that is set to true on enter and false on exit. If it is true in the OnCollisionEnter, it means it was already taken care and you should ignore the method.
bool sentinel = false;
void OnCollisionEnter(Collision col){
if( sentinel == true){ return; }
sentinel = true;
// Collision code
}
I have a pair of OnTriggerEnter and OnTriggerExit, in my case, the pair is called, I don't have like 4 onTriggerEnter when the $$anonymous$$eshCollider moves in the BoxCollider but 4 pairs respectively of OnTriggerEnter and OnTriggerExit, even if the whole $$anonymous$$eshCollider is envelopped by the BoxCollider. The problem didn't appear with a x10 scale weirdly.
Your way should work, but I feel it's like "cooperating with the bug" though.
The fact you get multiple collision resolution is not a bug, it has to be.
Consider you have a car and you want to apply a dent on the paint when it hits a wall. If you get only the first one, what if it is under the car? You see no dent. You want to know all of them so you can act realistically.
If you are only interested in was there a collision (one or many, no care), then you need to use the sentinel principle.
Answer by ninja_gear · May 20, 2016 at 02:07 PM
Like suggested in your comments, the easiest way to stop unwanted repetition of behavior to to put a Sentinel value into the object.
bool sentinel = false;
void OnCollisionEnter(Collision col)
{
if (!sentinel)
{
sentinel = true;
// Do stuff once ('hit' the jar/'hit' the bar)
}
}
void OnCollisionExit(Collision col)
{
if (sentinel)
{
sentinel = false; //Allows for another object to be struck by this one
}
}
Answer by DRsabadash · Mar 17, 2017 at 08:01 AM
For some reason, setting a boolean check for colliders can sometimes cause the boolean value to either flip, or to turn on/off the OnTriggerEnter/OnTriggerExit methods while remaining in the trigger area, like opening a door and closing it repeatedly while in the trigger area, or flipping the boolean value so it closes when you approach and opens when you walk away.
using a simple variable iterator prevents the actual method from being called repeatedly, guaranteeing only one execution per collision.
//previous code in class
//using a door opening and closing as an example
[SerializeField] private GameObject device;
private int i = 0;
void OnTriggerEnter(Collider other){
DoorScript door = device.GetComponent<DoorScript>();
if (i == 0) {
if (door != null) {
door.Operate ();
i++;
}
}
}
void OnTriggerExit(Collider other){
DoorScript door = device.GetComponent<DoorScript>();
if (i == 1) {
if (door != null) {
door.Operate ();
i = 0;
}
}
}
/* All DoorScript contains is a function Operate() and a boolean for if the door is open, and an if/else statement in Operate() for moving door to open if bool is false (set to closed) and moving door to closed if bool is true (set to open)
Your answer
Follow this Question
Related Questions
Help with OnTriggerEnter issue 3 Answers
Box collider with strange behaviour 1 Answer
OnTriggerExit doesn't work when scaling collider 0 Answers
OnTriggerExit happens too soon! 1 Answer
BoxCollider Triggers Twice even with isColliding Check 0 Answers