Search Unity

Bug Physics2D Layer Collision Matrix is buggy with specific layer numbers.

Discussion in 'Physics' started by aegis123321, Jan 11, 2022.

  1. aegis123321

    aegis123321

    Joined:
    Jul 5, 2015
    Posts:
    54
    So the thing is, I did instantiate a dynamic object as a bullet and a static body object as an obstacle and reassign the obstacle's layer right after instantiation.
    Their layers are "Buggy" and "Static-Hero-NoDynamic" which I've made sure they don't collide each other by Layer Collision Matrix.

    But they're collided in game!

    Here is my emitter scirpt:
    Code (CSharp):
    1. public class BuggyLayer : MonoBehaviour {
    2.     public GameObject bulletPrefab;
    3.     public GameObject obstaclePrefab;
    4.     public int overrideObstacleLayer = 16; // 16="Static-Hero-NoDynamic" layer
    5.  
    6.     void Update() {
    7.         ReproduceBug();
    8.         this.enabled = false;
    9.     }
    10.  
    11.     private void ReproduceBug() {
    12.         GameObject go = InstantiateBullet();
    13.         go.transform.SetParent(this.transform);
    14.         go.transform.localPosition = Vector3.zero;
    15.         go.transform.localRotation = Quaternion.identity;
    16.         go.transform.localScale = Vector3.one;
    17.         go.SetActive(true);
    18.         InstantiateObstacle();
    19.     }
    20.  
    21.     private GameObject InstantiateBullet() {
    22.         return Instantiate(bulletPrefab);
    23.     }
    24.  
    25.     private void InstantiateObstacle() {
    26.         GameObject go = Instantiate(obstaclePrefab);
    27.         go.SetActive(true);
    28.         go.layer = overrideObstacleLayer;
    29.     }
    30. }
    Here is the reproduce steps:


    And you can see that after I checked and unchecked the layer collision matrix, it works.
    I thought it was kind of only in editor, but I've tried to build a standalone and it still happen.

    There is an another point that I log some information by OnCollisionEnter2D.
    Code:
    Code (CSharp):
    1.  
    2. private void OnCollisionEnter2D(Collision2D collision) {
    3.     Debug.Log($"{collision.collider} collides {collision.otherCollider}!");
    4.     int layer1 = collision.collider.gameObject.layer;
    5.     int layer2 = collision.otherCollider.gameObject.layer;
    6.     Debug.Log($"Their layers are {layer1} and {layer2}\n" +
    7.         $"GetIgnoreLayerCollision({layer1}, {layer2})= {Physics2D.GetIgnoreLayerCollision(layer1, layer2)}\n" +
    8.         $"GetIgnoreLayerCollision({layer2}, {layer1})= {Physics2D.GetIgnoreLayerCollision(layer2, layer1)}");
    9. }
    10.  
    And result:

    Notice that Physics2D.GetIgnoreLayerCollision(27, 16) and Physics2D.GetIgnoreLayerCollision(16, 27) have different results, which is absolutely TERRIBLE.

    There're some information that might could help to find the reason.
    1. If I remove "go.layer = overrideObstacleLayer;", which means I don't reassign layer after instantiation, it works.
    2. If both objects are not instantiate at the same frame, it works.
    3. If I change the "buggy" layer to other id instead of 27, it works. <----- this is the weirdest thing.
    (For example, the layer "Rope" in project is totally same with "Buggy" but it's 13, and it don't have this issue.)


    It's a definitely weird and terrible bug and it's hard to realize how does it happen.
    And I'm also afraid if there's other layers have the same issue.

    Unity2019.4.30f1
    Case 1394017
     
  2. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,428
    This actually looks like the dataset for the settings is corrupted. If I reset it (maybe clear all the layers) then play, it works. If I select only those layers to contact it works. If I set everything then reset those layers it works.

    I guess the question becomes one of, how did it get such bad values? Note that this also works the same if I transfer that data to 3D physics i.e. it's not a physics system thing, it's bad data and potentially something in the shared layer-collision-matrix UI went bad. That was changed a while back by the 3D physics team to add the row/column highlight and the Enable/Disable all so maybe something odd happened there.

    It might be related to this that was fixed: https://issuetracker.unity3d.com/is...returning-values-that-do-not-match-the-editor

    I'll investigate the actual data to see why it's not displaying correctly in the matrix.

    We *might* be able to get it backported to 2019 if it is the above bug fix but I'd need to check with release managers.
     
  3. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,428
    Yes, confirmed, it's that bug that was fixed. I'll see if I can get permission to backport that far back (2019).
     
    aegis123321 likes this.
  4. aegis123321

    aegis123321

    Joined:
    Jul 5, 2015
    Posts:
    54
  5. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,428
    Yes, it's a shame we cannot always backport every fix back to all release versions but because of LTS status, it has to be a higher priority (HUP - High User Pain). The priority of the previous submission was very low (the only report of it) and it'd been like that for many years (not a regression).

    This being a duplicate bumps up the priority a bit so I'll try again. Are you planning on staying with 2019? I only ask because I might be able to get back to 2020.3 without too much issue but 2019.4 will potentially more difficult although the fix does include several extra unit-tests on our build farm so it might not be too hard after all.
     
  6. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,428
    BTW: I've marked your case as a duplicate because I need to use the original submission report. You can track that here and it should eventually show other backports as "In Review". I will of course post back here to give you an update ASAP.

    Sorry for this issue.
     
  7. aegis123321

    aegis123321

    Joined:
    Jul 5, 2015
    Posts:
    54
    We don't have plan to upgrade since the project is pretty huge.
    It's okay. now I understand how it happens, I think I am able to fix the dataset by myself.
     
  8. aegis123321

    aegis123321

    Joined:
    Jul 5, 2015
    Posts:
    54
    OK, I tried to make a editor script to fix the dataset and it works well in Unity2019.4.
    code:
    Code (CSharp):
    1. public static class FixPhysics2DLayerCollisionMatrix {
    2.     [MenuItem("Custom/Fix Physics2D Layer Collision Matrix")]
    3.     public static void Fix() {
    4.         for (int layer1 = 0; layer1 < 31; layer1++) {
    5.             int layer1Mask = Physics2D.GetLayerCollisionMask(layer1);
    6.             for (int layer2 = layer1 + 1; layer2 < 31; layer2++) {
    7.                 int layer2Mask = Physics2D.GetLayerCollisionMask(layer2);
    8.                 bool layer1CollideLayer2 = (layer1Mask & (1 << layer2)) != 0;
    9.                 bool layer2CollideLayer1 = (layer2Mask & (1 << layer1)) != 0;
    10.                 if (layer1CollideLayer2 != layer2CollideLayer1) {
    11.                     string collideInfo = $"{LayerMask.LayerToName(layer1)}({layer1}) vs {LayerMask.LayerToName(layer2)}({layer2})";
    12.                     Debug.Log(
    13.                         $"Found conflicted layer mask : {collideInfo}");
    14.                     int option  = EditorUtility.DisplayDialogComplex("Should Collide?",
    15.                         $"{collideInfo}, should collide?", "Collide", "Don't change", "Not collide");
    16.                     switch (option) {
    17.                         case 0: // Yes.
    18.                             layer1Mask |= (1 << layer2);
    19.                             layer2Mask |= (1 << layer1);
    20.                             Physics2D.SetLayerCollisionMask(layer1, layer1Mask);
    21.                             Physics2D.SetLayerCollisionMask(layer2, layer2Mask);
    22.                             Debug.Log($"Fix {collideInfo}, they collide each other.");
    23.                             break;
    24.                         case 1: // Cancel.
    25.                             break;
    26.                         case 2: // No.
    27.                             layer1Mask &= ~(1 << layer2);
    28.                             layer2Mask &= ~(1 << layer1);
    29.                             Physics2D.SetLayerCollisionMask(layer1, layer1Mask);
    30.                             Physics2D.SetLayerCollisionMask(layer2, layer2Mask);
    31.                             Debug.Log($"Fix {collideInfo}, they don't collide each other.");
    32.                             break;
    33.                         default:
    34.                             break;
    35.                     }
    36.                 }
    37.             }
    38.         }
    39.         Debug.Log("Fix done!");
    40.     }
    41. }
    result:
     
  9. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,428
    That's great to hear, again sorry for the troubles.

    I've got permission for 2020 but I'll need to wait for 2019.4
     
  10. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,428
    aegis123321 likes this.
  11. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,428
    Just to finish this off, the final backport landed this morning in 2019.4.35f1.

    Again, thanks for reporting this was still an issue.
     
    firebird721 and aegis123321 like this.