Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

2019 changes behavior of OnTriggerExit2D

Discussion in 'Physics' started by mhardy, Jan 14, 2020.

  1. mhardy

    mhardy

    Joined:
    Apr 3, 2011
    Posts:
    48
    I just tried to upgrade a game from 2018 to 2019 and everything went crazy. After hours of digging I discovered that 2D triggers changed when they get called.
    • Physics: Ensured that 2D trigger/collision exit callbacks occur when destroying a GameObject inside a 2D trigger/collision callback. (1057320)

    • Physics: Ensured that 2D trigger/collision exit callbacks occur when disabling a GameObject or 2D collider component. (1071700)
    Is there any way to disable this "fix"?

    I can see how some might consider this a bug, but I've built games around this behavior as it's been this way for years. I have one game that relies heavily on it working the way it did. Just because I disable a game object that has entered a 2D box, I don't consider that leaving the box and I don't want it triggering all the OnExit logic.

    This seems like a massive breaking change.
     
  2. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,321
    The following should control that: Physics2D.callbacksOnDisable

    Note that the cases you refer to are not the feature implementation but bug-fixes for the feature where exit is called upon delete/disable. That feature has been in since Unity 5.6. What might have changed is that the template default for it has changed to true. There have been a lot of changes to templates and frustratingly the defaults get changed sometimes.

    BTW: The referencing to "Disable" and not "Delete" is because deletion first starts with disabling. Also, it's make no sense to have two identical options that both do the same thing.

    Hope this helps.
     
  3. mhardy

    mhardy

    Joined:
    Apr 3, 2011
    Posts:
    48
    Thanks, that does help. And gets me much closer. However, even when set to false, disabling a game object still causes OnTriggerExit2D() to fire. DESTROYING, a game object with callbackOnDisable set to false no longer does, but disabling them still does.

    e.g.

    Code (CSharp):
    1. void Awake()
    2. {
    3.    Physics2D.callbacksOnDisable = false;
    4. }
    5.  
    6. public void DisableGun()
    7. {
    8.    // this is what I want to do... but OnTriggerExit2D gets called
    9.    Gun.gameObject.SetActive(false);
    10.  
    11.    // OnTriggerExit2D is not called (but I don't want to destroy my gun)
    12.    Destroy(Gun.gameObject);
    13. }
     
  4. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,321
    That is very odd and certainly shouldn't be the case.

    Can I ask what Unity version this is and if it only happens with triggers?
     
  5. mhardy

    mhardy

    Joined:
    Apr 3, 2011
    Posts:
    48
    Unity version 2019.2.17f1

    I only use triggers here so that's all I can speak to.
     
  6. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,321
    Okay thanks, I'll have to investigate that at some point next week. If you feel up to it, you can submit a bug report, give me the case number and I'll get back to you on it. It'll also give you an easier method to track any subsequent fix.
     
  7. mhardy

    mhardy

    Joined:
    Apr 3, 2011
    Posts:
    48
    Done. Case 1212896 and included simple test project to repro.
     
  8. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,321
    Thanks. I've got the case and will look at this early next week.
     
  9. mhardy

    mhardy

    Joined:
    Apr 3, 2011
    Posts:
    48
    I took a closer look and determined it wasn't the default that changed. The default for Physics2D.callbacksOnDisable appears to have been 'true' for both 2018 and 2019, but the behavior has changed as follows with a small Rigidbody2D inside a large BoxCollider2D on start:

    Physics2D.callbacksOnDisable = true; // or false

    // 2018.4.16.f1
    // true (or not set):
    // - OnEnter called on Start
    // - OnExit NOT called during disable, CALLED on Destory
    // false:
    // - OnEnter called on Start
    // - OnExit never called

    // 2019.2.9f1
    // true (or not set):
    // - OnEnter called on Start
    // - OnExit always called
    // false:
    // - OnEnter called on Start
    // - OnExit CALLED on disable (BUG), NOT called on destroy
     
  10. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,321
    I was referring to the defaults in the templates when you create a new project. Those are not controlled by physics. The defaults you get when you reset the project settings for instance are not the defaults the templates set when you create a new project. Those templates have had many problems for lots of teams with defaults being set wrong. These issue for 2D/3D physics in templates were fixed,

    Also, that was my first post in reply to you before I even knew what was going wrong. As you should be able to see here, we've got and accepted your bug report the day after it was submitted: https://issuetracker.unity3d.com/issues/ontriggerexit2d-when-disabling-a-gameobject

    You can use this to track the fix as the status will show up.
     
    Last edited: Jan 29, 2020
  11. mhardy

    mhardy

    Joined:
    Apr 3, 2011
    Posts:
    48
    Got it! Thanks for clarifying. Will follow the issue tracker.
     
  12. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,321
    Sorry for the delay but wanted to say that today this has been fixed. I'll organise getting it into the release stream including backports but note it will take a little while depending on the release schedules etc.

    Thanks for raising the bug, very much appreciated and sorry for the hassle.

    I wanted to add that the options was "technically" working as it was originally designed to control whether the callback happened synchronous to you performing the disable/deactive and that is controlled correctly. If you check, you'll see that immediately after you do so, you don't get a callback. The problem comes later when the simulation steps; at the end of that, the callbacks are performed and the contact state is "Exit" so is actually reported.

    So for consitency, we now explicitly check to see if the condition of an Exit callback on a collider pair where at least one of the colilders is disabled/deactivated when the CallbacksOnDisabled is false. If that's the case we don't report it to be consistent. Anyway, thought it worth explaining that.

    What's even more annoying is that the reason this wasn't found in the unit-tests was that the tests were verifying that the callback didn't happen immediately but then went on to verify that they did when the simulation ran so they were checking for the condition you reported. Changing the tests to check for no callback after a simulation step reveals the issue immediately. Doh!
     
    Last edited: Feb 6, 2020
  13. Luminoth

    Luminoth

    Joined:
    Jan 15, 2013
    Posts:
    25
    Hi, will the fix for this also fix the same issue occurring when Rigidbody2D.isKinematic is set to true at runtime? I'm seeing assigning that causing OnTriggerExit2D() to occur when it was not on the same project in a 2018 build.
     
  14. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,321
    Best not to assume it's the "same issue" as this is a very common thing we see which is unfortunately why we don't see bug reports. Many things can cause contacts to be destroyed (Exit called). I don't have a bug report on the behaviour you just stated at all. Did you submit one? If not then I would ask if you could do that. In the very least I can answer your question.

    FYI: When you change the body-type, Box2D will destroy all the contacts as it's a non-trivial change. We flag them for recreate when you do that and try to not report them so you can pretend it didn't happen and "all" you did was change the body-type but of course it did make those changes. It's not just a property after all but has side-effects.

    Note that this property has been deprecated for a very long time. You should use Rigidbody2D.bodyType (same as that which appears in the Inspector).
     
    Luminoth likes this.