• Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
0
Question by schkolne · Aug 21, 2015 at 08:28 PM · rigidbodyontriggerentertriggersontriggerexit

OnTriggerExit doesn't fire when changing RigidBody (bug? feature?)

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 ;)

Comment
Add comment · Show 1
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image schkolne · Sep 02, 2015 at 12:57 AM 0
Share

Hey - so, an update, in part thanks to the folks at Unity ;).

The issue seems to be clarified by looking at the wonderful Unity execution order diagram. You see, OnTriggers are called after FixedUpdate.

So, it seems that if you move something in, and out of a trigger in an Update, when later FixedUpdate is called it completely misses the relevant triggers.

We are now working on a solution where we, after moving, explicitly wait for a FixedUpdate before proceeding. There are many ways to go about this. One of them is using the "yield WaitForFixedUpdate" construct to have some code that fires after the FixedUpdate. This is a bit messy as it spawns a new thread which, in our particular application, causes some issues. So we are trying some other stuff out, all of which is way beyond the scope of this thread;).

To answer my original question, posed in the title -- this is not a bug but apparently a feature. Triggers are only processed after FixedUpdate, and if you do something in an Update that should cause a Trigger, then do something else -- well you may not get your triggers. If you need a trigger you should basically wait for it.

There is an alternate $$anonymous$$dset, which is to do all motion in the FixedUpdate which (as many of us know) is a general Unity principle that we should all try to follow. This still may lead to weird behavior, in that if multiple kinds of trigger-collisions happen, with reparenting and what not from within FixedUpdate, you may not get all your triggers. That's at least what we found when we did the trivial change of Update to FixedUpdate in the core code region.

The real lesson we learned is "wait for the trigger" aka "wait for the FixedUpdate". That guiding principle seems to promise a workable, robust solution. If this fails well expect me to post here again ;).

2 Replies

· Add your reply
  • Sort: 
avatar image
0

Answer by schkolne · Aug 23, 2015 at 05:00 AM

Cool some good thoughts thank you!

As for insight #1: It's true Unity frowns upon setting Rigidbody positions directly. I went in and changed the code on frame 12 to affect the Rigidbody position instead of the gameobject, like so:

         if (Time.frameCount == 12) {
             transform.parent = debugRigidBody2.transform;
             debugRigidBody2.GetComponent<Rigidbody>().position += new Vector3(0, 0, .4f);
         }
 

The behavior is the same and I don't get the OnTriggerExit that I'm looking for.

As for insight #2: The reasons for using a Rigidbody on the sphere are due to other parts of this system. That said, we could consider designing our system to not use Rigidbodies if that would help.... one reason we're using a Rigidbody is that, on this page, you can see at the bottom that the Kinematic Rigidbody Trigger Collider sends trigger messages in all cases and is the most general.

That said, i did a quick test and removed the Rigidbody from the Sphere. The behavior remains the same (no OnTriggerExit on or around frame 12).

Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image
1

Answer by FortisVenaliter · Aug 21, 2015 at 08:35 PM

The problem is likely that you are moving the rigidbody yourself. Rigidbodies are defined by the physics system, and expect to only be moved by forces and torque. Changing the position manually "pops" it, which is an unexpected behaviour for the physics engine. It handles it pretty well, but it doesn't surprise me that it fails on some collision calls as a result.

Also, why would you use a rigidbody on a trigger collider? If it's a trigger, it can't properly interact with the physics system, so it seems like it would be redundant and superfluous. Try removing the RigidBody for the sphere and see if the collision works a bit better. There are pretty specific rules to how rigidbody colliders and non-rigidbody colliders interact. Read this page for more info.

Comment
Add comment · Show 2 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Owen-Reynolds · Aug 22, 2015 at 03:20 PM 0
Share

But, the thing is, TriggerEnter does work for manual movement. It's working in the code above, which moves by hand. And I think it purposely works for non-physics moves in general. I sometimes use it that way, with no problems.

I think the entire error (which the OP should have put in the title!!!) is about changing the parenting on the same frame in which you leave(?) a trigger. I think this may be a real not-working thing. It may confuse the trigger about whether you were in it last frame.

avatar image schkolne · Aug 23, 2015 at 10:14 PM 0
Share

Hi Owen - I tried to put it in the title - sorry if it was unclear. I fully agree that changing the parenting (aka changing the rigidbody) is what's causing the issue. That's the difference between frame 12 and 6 in my source code example.

$$anonymous$$y question is: is this a bug? is this a feature? what is supposed to happen when you change a parent, with OnTriggerExits?

Also - FortisVenaliter - I responded to your Answer below, as a separate reply (not comment) so you may not have gotten it, curious to hear your thoughts.

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Welcome to Unity Answers

If you’re new to Unity Answers, please check our User Guide to help you navigate through our website and refer to our FAQ for more information.

Before posting, make sure to check out our Knowledge Base for commonly asked Unity questions.

Check our Moderator Guidelines if you’re a new moderator and want to work together in an effort to improve Unity Answers and support our users.

Follow this Question

Answers Answers and Comments

2 People are following this question.

avatar image avatar image

Related Questions

OnTriggerExit happens too soon! 1 Answer

OnTriggerEnter is not working! I have tried absolutely everything I can think of. 1 Answer

OnTriggerEnter, OnTriggerExit Work Only Once 2 Answers

OnTriggerEnter/Exit called unexpectedly 2 Answers

OnTriggerEnter works, OnTriggerExit doesn't 3 Answers


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges