I’m seeing the following funny thing:
- when you change the RigidBody of a GameObject, and move it on the same frame, you do not get OnTriggerExit (on that object or on an object it intersects).
I have looked everywhere online and can’t find anyone trying to do this or talking about this issue. In the Unity docs, I can’t find a spec on what should happen in this scenario.
This is a deep thing we found in a big project and figuring out a way around this is very important for us.
My questions are:
- Is this a bug?
- If so can we get a fix
- If not, is there a workaround?
- We have found a workaround, which involves OnTriggerStay (even though we don’t get an OnTriggerExit, we do see that OnTriggerStay stops getting called). This seems computationally heavy - any insight/advice here?
We have spent dozens of hours on this issue and are keen to do whatever it takes to get to the bottom of this ;).
Here’s the setup:
- Scene has a Cube and a Sphere, as well as two rigidbodies (debugRigidBody1, debugRigidBody2)
- Sphere is Kinematic Rigidbody Trigger Collider and never moves (RigidBody is on the sphere, IsKinematic, no gravity) (Sphere collider on Sphere, isTrigger checked)
- Sphere NEVER MOVES OR CHANGES.
- Cube has a non-trigger Collider on it. Starts out intersecting the Sphere in the scene. The Cube is not parented to anything and thus, at the beginning is thus what I believe one would call a Static Collider.
This script is attached to the Cube:
public class DebugCube : MonoBehaviour {
public GameObject debugRigidBody1;
public GameObject debugRigidBody2;
void Update () {
Debug.Log("---- ---- Update, frame is " + Time.frameCount + " ---- ---- ");
if (Time.frameCount == 1) Debug.LogError("timeout");
if (Time.frameCount == 2) {
transform.parent = debugRigidBody1.transform;
}
if (Time.frameCount == 6) {
transform.position += new Vector3(0, 0, .4f);
}
if (Time.frameCount == 8) {
transform.position -= new Vector3(0, 0, .4f);
}
if (Time.frameCount == 12) {
transform.parent = debugRigidBody2.transform;
transform.position += new Vector3(0, 0, .4f);
}
}
}
This script is attached to the Sphere:
public class DebugSphere : MonoBehaviour {
void OnTriggerEnter(Collider other) {
Debug.Log("Sphere OnTriggerEnter " + other.gameObject.GetInstanceID());
}
void OnTriggerStay(Collider other) {
Debug.Log("Sphere OnTriggerStay " + other.gameObject.GetInstanceID());
}
void OnTriggerExit(Collider other) {
Debug.Log("Sphere OnTriggerExit " + other.gameObject.GetInstanceID());
}
}
Running this in Unity (tried it in 5.1.1 and 5.1.2) I see that:
- On Frame 2, I get an OnTriggerEnter
- On Frame 6, I get an OnTriggerExit
- On Frame 8, I get an OnTriggerEnter
- I expect an OnTriggerExit on Frame 12 but I don’t get one. (well, “expect” is a strong word. I want one ;). But not sure if I should “expect” one (bug or feature?)).
- I notice that I get OnTriggerStays for frames 8, 9, 10, 11, but none for frames 12 and after.
For the purposes of further investigation, I made a modification of this code where, when (Time.frameCount == 12), I set transform.parent but comment out the line that changes transform.position. Here I see the curious behavior that on Frame 12 I get an OnTriggerEnter (ostensibly because, the new RigidBody is “entering” the Sphere’s collider).
Please help me understand what’s going on here! Please please please