Search Unity

Bug OnTriggerExit2D doesn't work by changing localScale to a tiny number.

Discussion in 'Physics' started by aegis123321, Apr 14, 2021.

  1. aegis123321

    aegis123321

    Joined:
    Jul 5, 2015
    Posts:
    71
    OnTriggerExit2D doesn't work with all types of collider which has tiny localScale except for circle collider.

    There are a box trigger and a circle collider in the scene.


    And box trigger has a script to log the trigger callbacks like this:
    Code (CSharp):
    1.  
    2.     private void OnTriggerEnter2D(Collider2D collision) {
    3.         Debug.Log($"{this.gameObject.name}'s OnTriggerEnter2D: {collision.gameObject.name}");
    4.     }
    5.  
    6.     private void OnTriggerExit2D(Collider2D collision) {
    7.         Debug.Log($"{this.gameObject.name}'s OnTriggerExit2D: {collision.gameObject.name}");
    8.     }
    9.  
    And a script to reproduce this bug:
    Code (CSharp):
    1.  
    2. public class SetLocalScale : MonoBehaviour {
    3.     public Transform target;
    4.     public float targetScale = 0.001f;
    5.  
    6.     IEnumerator Start() {
    7.         // Wait OnTriggerEnter2D.
    8.         yield return null;
    9.  
    10.         Debug.Log($"Set {target.gameObject.name}'s localScale to {targetScale}");
    11.         target.localScale = new Vector3(targetScale, targetScale, 1f);
    12.     }
    13. }
    14.  
    So the idea is the box trigger should scale to the targetScale at the second frame and two shapes won't overlap, then the OnTriggerExit2D() will be invoked.

    It works fine with targetScale=0.1f.
    but it doesn't work with targetScale=0.001f.

    video: https://i.imgur.com/creUxOk.mp4

    Case 1329061
     
  2. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,491
    This is likely because you've created a degenerate shape i.e. you've scaled it below what can be dealt with by the physics system (Box2D). Do you get a warning on that collider telling you that this is the case and that no shapes could be created? I bet the collider is already small and you scaled it down to 1/1000th its size. That'll be the issue. You create this degenerate situation when vertex become to close in a similar way to when you create an EdgeCollider2D with intersecting edges; it won't like it. The Box2D polygon vertex limit is 0.0025 which is incredibly small. Circles are not affected by this because they only have a radius and it's clamped at the lower-bound. Polygons cannot simply do this and become degenerate.

    Physics (Box2D) does not have a way to change sizes of things like this so using Unity Transform scale means the collider(s) have to be recreated. To ensure you don't get a new Enter/Exit when you do such an action we have to store the existing state and ask for it to be recreated. If that fails then it's left in an undefined state. Could we "detect" this? We might be able to but it also might be hard to do without creating a bunch of overhead detecting it too.

    NOTE: You can detect this by calling Collider2D.shapeCount which will give you the count of non-degenerate shapes. If this is zero then you've scaled it way below what is possible and can expect problems.
     
  3. aegis123321

    aegis123321

    Joined:
    Jul 5, 2015
    Posts:
    71
    No, I didn't get any warning about this.

    You've stored the state before recreated. Does it hard to detect if the shape is degenerate and send a Exit if it has entered before?

    Thanks for explanation.
    It's not a big issue tho. Just feeling it should be handled.
    Or be an option like "Callbacks On Disable" do in ProjectSettings.
     
  4. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,491
    Are you sure? I find that hard to believe. I'm not talking about the console, I mean in the inspector on the collider you're scaling down.
     
  5. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,491
  6. aegis123321

    aegis123321

    Joined:
    Jul 5, 2015
    Posts:
    71
    Oh I see. I thought you are talking about console.

    As you said, if shape count is a way to check the degenerate shape. It should not that hard to check them when you recreate the shape, right? I just want the Enter and Exit callbacks are always pair.