Ahoy, I have used these two frequently and never ha a particular issue. However I recently started a new project and was trying to do something pretty simple (when a character walks into the trigger, target them.
But for whatever reason when I did it, it began rapid fire enter/exiting over and over again.
And when I affixed it to an empty game object with a trigger box it worked fine. So I put it on the character it was supposed to be on. Went back to freaking out and doing both endlessly.
So I tried taking things away until eventually I took away the nav mesh agent (since this is to be an NPC) and suddenly it starts behaving again.
Does anyone have any ideas regarding why/how I could fix this? I had, in a previous project, very successfully attached a similar script to a nav mesh agent. Has changes to the Nav Mesh Agent in v5 made this no longer a thing?
So i ran into your problem as well with my project and with a little messing around i figured it out sorta. My AI Character has a Rigidbody attached to him so he can activate Triggers and under the Rigidbody’s settings i turned "Is Kinematic " on and now both OnTriggerEnter and OnTriggerExit are called as they are expected to. I’m not really sure why this happens but it seems to fix it for me.
Beginners check this: I had a similar result for a completely different (and obvious when you think about it) cause. I had the collider box attached to an animated door object. When the door was triggered, it rotated and took the collider box with it. So all of a sudden, the third person controller that had triggered the box was no longer in the box, despite having not moved. Therefore, the trigger on exit was activated and the door shut again. So the collider returned and triggered the on entry function again which opened the door again. Ad infinitum.
Moral: put the collider box on an empty and not on the animated object. But you probably knew that anyway.
I have this problem and I don’t think any of this solutions are good.
I’ve focused the problem and made 2 simple capsule colliders, with rigidbodies set to discrete detection, non kinematic, with no tag check on the ontriggerenter/ontriggerexit functions. The first capsule had a navMeshAgent (representing the npc) and the second capsule doesnt. Also I added a list, where I add elements in ontriggerenter and remove them on ontriggerexit, to notice when detection occurs.
So, as I said:
The solution of removing tags it’s of no use because without the tag check the problem persists
The solution of rigidbody to continuous resolves the problem but if you have lots of npc’s its going to hit performance
The solution of IsKinematic is the worst of all, because you won’t have physics collisions interactions right out of the box (npc will pass through the player for example)
What I’ve found:
It seems that the problem is related to the navMeshAgent and the rigidbody somehow. In my case after a minute or less the elements on the list of the npc start to dissapear and then begins the cycle of adding/deleting on ontriggerenter/ontriggerexit. BUT if i tick the freeze position on the y axis, its seems to stop. I’ve noticed that once you press play, you can’t move the navmeshagents in the Y axis with your mouse, so I’m assuming you had to do code anyway to move your npc vertically. I don’t think this is a perfect solution anyway, and looks like a bug to me.
I got this bug today in Unity version 5.5.0.f3
Two Box Colliders 2D → TriggerEnter & TriggerExit fire at the same time.
I find somethere it should be caused by resizing the colliders, but I did’t resize anything.
However, I give up after 4 hours for now.
Rigidbody collision detection to Continuous did not help in my case.
The only solution I see, a workaround with some kind of timer after the first TriggerEnter, to do stuff I need on TriggerExit.
It actually seems to be a problem related to how NavMeshAgent and Rigidbody interact with each other when placed on the same GameObject.
I didn’t track down the exact cause for this behaviour, but I guess the simplest and probably least expensive fix would be to force the Rigidbody to sleep. It will automatically wake up a frame later due to the movement caused by the NavMeshAgent, but it no longer causes the Triggers to malfunction.
I ran into the same problem but for me it turned out because I put “rb.detectCollisions=false;” in OnTriggerEnter(). So when it entered, it stopped detecting collisions, that triggered it as exited which starts detects again so it triggers at enters and so on.
For those who need isKinematic==false before enter the trig,here is the “right anwser” from AI.
using System.Collections.Generic;
using UnityEngine;
public class TestTriggerHandle : MonoBehaviour
{
private HashSet<Collider> _enteredThisFrame = new HashSet<Collider>();
private HashSet<Collider> _exitedThisFrame = new HashSet<Collider>();
public BaseInvoke invoke_in;
public BaseInvoke invoke_out;
void OnTriggerEnter(Collider other)
{
// 如果该物体在本帧已触发退出,则抵消
if (_exitedThisFrame.Contains(other))
{
_exitedThisFrame.Remove(other);
return;
}
_enteredThisFrame.Add(other);
}
void OnTriggerExit(Collider other)
{
// 如果该物体在本帧已触发进入,则抵消
if (_enteredThisFrame.Contains(other))
{
_enteredThisFrame.Remove(other);
return;
}
_exitedThisFrame.Add(other);
}
void LateUpdate()
{
// 处理所有未被抵消的进入事件
foreach (var collider in _enteredThisFrame)
{
Debug.Log($"处理进入: {collider.name}");
// 实际逻辑...
//actual logic:invoke_in.DoInvoke();
}
// 处理所有未被抵消的退出事件
foreach (var collider in _exitedThisFrame)
{
Debug.Log($"处理退出: {collider.name}");
// 实际逻辑...
//actual logic: invoke_out.DoInvoke();
}
// 清空缓存
_enteredThisFrame.Clear();
_exitedThisFrame.Clear();
}
}
Here’s my point.
The physics system acctually triggers enter and exit multiple times in one frame,they comes in pairs and finally end at “enter” or “exit”. So you need this kind of code to handle that,then do your own logic in LateUpdate.
Function in scripting are called in order of appearance in the script. Try switching places of your two function lines void OnTriggerEnter and void OnTriggerExit. It should look something like this:
using UnityEngine;
using System.Collections;
public class NavMeshAgent : MonoBehaviour {
void OnTriggerEnter (Collider col)
{
if (col.tag == "Player")
{
print (col.name);
}
}
void OnTriggerExit (Collider col) {
if (col.tag == "Player")
{
print (col.name);
}
}
}
Be sure to make sure the class name and script name are the same if you are going to change the name of the script. Hope this helps