Search Unity

  1. Unity 2019.1 is now released.
    Dismiss Notice

Collision triggered but no contact?

Discussion in 'Scripting' started by bawenang, Jul 8, 2013.

  1. bawenang

    bawenang

    Joined:
    Aug 18, 2012
    Posts:
    102
    Hi guys,
    I tried to detect the contact point of my player yet it sometimes crashed when it runs this line:

    Code (csharp):
    1.  
    2. ContactPoint contactPt = hit.contacts[0];
    3. GameObject goCol = contactPt.thisCollider.gameObject;
    4.  
    Apparently, there is no contact at all although the collision on enter is triggered. How can you collide if you don't have any contact? Can anyone help me here? I need to always know the point of contact of my player's collision to determine which part of the composite collider that received the collision.

    Thanks in advance.

    EDIT: From the documentation: "Every contact contains a contact point, normal and the two colliders that collided (see ContactPoint). From inside OnCollisionStay or OnCollisionEnter you can always be sure that contacts has at least one element. "

    Okay, so why does my game crash because there's no element at all in the contact array?
     
    Last edited: Jul 8, 2013
  2. shaderop

    shaderop

    Joined:
    Nov 24, 2010
    Posts:
    942
    Where is the error happening exactly? Is hit.contacts null? Or is it empty? Or is the contactPt.thisCollider null, or is it contactPt.this.Collider.gameObject? And can you share the whole OnCollision method? That might help.
     
  3. bawenang

    bawenang

    Joined:
    Aug 18, 2012
    Posts:
    102
    Hi, sorry for the late reply. I was busy with other things. The hit.contacts is not null but it's array is empty. Anyway, here's the script:

    Code (csharp):
    1.  
    2.     void OnCollisionEnter(Collision hit)
    3.     {
    4.         Debug.Log("Collision Bike hitting = " + hit.gameObject.name + " velocity = " + hit.relativeVelocity);
    5.        
    6.         GameObject goCol = null;
    7.         if (hit.contacts.Length > 0) //Had to add this to check for contacts not empty
    8.         {
    9.             goCol = hit.contacts[0].thisCollider.gameObject;
    10.         }
    11.        
    12.         if ( goCol == null || goCol.tag == "Player")
    13.         {
    14.                
    15.             if (GameManager.instance.GetGamePlayerManager().LifeStatus() != GamePlayerManager.eLifeStatus.ALIVE || (!initSfx  hit.relativeVelocity.y > 2.0f))
    16.             {
    17.                 AudioSource sfx = SoundManager.instance.GetAvailableSfxSource("Rigidbody_Sound");
    18.    
    19.                 if (sfx != null)
    20.                     sfx.PlayOneShot(sfx.clip);
    21.             }
    22.             else
    23.                 initSfx = false;
    24.            
    25.             if (hit.gameObject.tag == "WaterCollider")
    26.             {
    27.                 GameManager.instance.GetGamePlayerManager().KillPlayer();
    28.             }
    29.             else if (hit.gameObject.tag == "Enemy")
    30.             {
    31.                 //Enemy enemy = hit.gameObject.GetComponent<Enemy>();
    32.                
    33.                
    34.                 /*
    35.                 if (enemy == null)
    36.                     GameManager.instance.GetGamePlayerManager().SetExplosionData( hit.contacts[0].point );
    37.                 else
    38.                     GameManager.instance.GetGamePlayerManager().SetExplosionData( enemy.deadExplosionForce,
    39.                                                                                   enemy.deadExplosionRadius,
    40.                                                                                   enemy.deadExplosionUpModifier,
    41.                                                                                   hit.contacts[0].point ); */
    42.                
    43.                 GameManager.instance.GetGamePlayerManager().KillPlayer();
    44.                 Debug.Log("KILL PLAYER! ");
    45.             }
    46.             /*else if (hit.gameObject.tag == "Item")
    47.             {
    48.                 Item item = hit.gameObject.GetComponent<Item>();
    49.                 power += item.value;
    50.                
    51.             }*/
    52.         }
    53.         else if (goCol != null  goCol.tag == "CharacterCollider") //This is what I need to check. Basically it's checking for another gameobject that is a child under the Player gameobject with the tag "CharacterCollider"
    54.         {
    55.             Debug.Log("CharacterCollider is hit! Kill Player because hitting = " + hit.gameObject.name);
    56.            
    57.             if (! (hit.gameObject.tag == "Enemy"))
    58.             {
    59.                 GameManager.instance.GetGamePlayerManager().SetExplosionData( hit.contacts[0].point );
    60.             }
    61.            
    62.             GameManager.instance.GetGamePlayerManager().KillPlayer();
    63.         }
    64.        
    65.     }
    66.  
     
  4. bawenang

    bawenang

    Joined:
    Aug 18, 2012
    Posts:
    102
    So, no one can help me here? The question is simple really, why is that sometimes the hit.contacts is empty when the hit is not and can be detected in the OnCollisionEnter function?
     
  5. Iamdain

    Iamdain

    Joined:
    Feb 3, 2010
    Posts:
    90
    same problem here, bumping for any answers...

    OnCollisionEnter fires but col.contacts is empty
     
  6. iansnyder

    iansnyder

    Joined:
    Dec 22, 2012
    Posts:
    10
    Same issue as Iamdain, after adding a few new box colliders to an object it seems when I hit some of them I get:
    var contact = collision.contacts[0];
    I'm getting an array index out of range. Not really critical for what I'm doing right now but it seems bad that the documentation specifically says this should never happen :p
     
  7. pmexcell

    pmexcell

    Joined:
    Feb 21, 2013
    Posts:
    1
    I too am experiencing this issue.

    I am optimizing a high-rigidbody2d-count physics simulation, and I converted a bunch of Instantiate/Destroy calls to using a pooled object solution. When a "bullet" collides with another object at a high enough speed, the bullet gets destroyed (now deactivated and returned to the pool). Both objects still register the collision, and what I'm seeing through the debugger is a third collision that has the empty contacts array error.
     
  8. technicat

    technicat

    Joined:
    Nov 22, 2006
    Posts:
    1,256
    I have this problem, too, in my bowling game, which hasn't caused it to crash, so it's been going on for a while. I wonder if it's a particular type of collision, like sphere on sphere. I don't see a bug report in the public Unity issues tracker, so I guess I'll have to narrow it down and file one at some point.
     
  9. EJSainz

    EJSainz

    Joined:
    Mar 24, 2015
    Posts:
    12
    Hello! I've just been experiencing this problem too, and solved it in a rather strange way.

    The solution was simple: commenting a line that was disabling the collider in Awake(). The strange thing is that this collider was being enabled somewhere else in the code - otherwise no collision would have happened.

    So my guess is that disabling the collider in Awake() prevents some internal code to work correctly (maybe the binding to physics engine), and makes for collisions without contacts.
     
  10. CreativeSpore

    CreativeSpore

    Joined:
    Nov 6, 2014
    Posts:
    1,061
    I was looking for answers here as well and I think I found a solution, so I will post it here in case someone finds it useful.
    In my case it was happening with a MeshCollider after updating it (changing any property like sharedMesh, convex or isTrigger), all other colliders colliding with it were triggering collision events with empty contacts array.
    The solution was, simply, setting the meshCollider convex property on next update (not the same the meshCollider was changed)
    Code (CSharp):
    1. bool m_applyColliderFix = false;
    2. void Update()
    3. {
    4.     if(m_applyColliderFix )
    5.     {
    6.         m_applyColliderFix = false;
    7.         m_meshCollider.convex = m_meshCollider.convex;
    8.     }
    9.     UpdateMeshCollider(); // this should be called after the above check
    10. }
    11.  
    12. void UpdateMeshCollider()
    13. {
    14.     m_meshCollider.convex = false;
    15.     m_meshCollider.isTrigger = false;
    16.     m_meshCollider.sharedMesh = new Mesh();
    17.     // if you do any of this, set the fix to be called on next update
    18.     m_applyColliderFix  = true;
    19. }
    Other solution is enabling and disabling the gameObject that is colliding with the meshCollider (in my case), but the first time you will have to lead with an empty contatcs array and the next time this collider will receive a filled array of contacts.
    Code (CSharp):
    1. public void OnCollisionStay(Collision other)
    2. {
    3.     if (other.contacts.Length == 0)
    4.     {
    5.         gameObject.SetActive(false);
    6.         gameObject.SetActive(true);
    7.         return;
    8.     }
    9. }
    10.  
    It looks like a bug and I found it even in the last version 5.3.5f1.
     
  11. Alexrose12345

    Alexrose12345

    Joined:
    Jul 15, 2012
    Posts:
    6
    So, I've been using Unity2D since December 2013 when it first came out.

    I've just started fiddling with Unity3D. And I get this. I'm doing exactly what I'd do in 2D but in 3D, does not work. Returns an empty array. This is on 4.2.4f1. I'm completely miffed! Like, is this real life? I'm not even modifying the collider in any way, I literally just have a flat plane and a capsule collider, and when I walk off the plane (using velocities, not by transform), I trigged a collision with a contacts array of size 0. Invariably! What on Earth?

    So I googled and this issue has existed for 5 years with no solution? I'm talking a barebones scene with basically nothing in it and the simplest functionality I can fathom, and this has somehow been a problem for 5 years and no one has a solution to this? What is that?

    And it seems like the only solutions I can find are like, "Yeah, just use a character controller". Like, my games are tailored, game feel is the most important thing in the entire game for me, there's no way I'm using an "out of the box" controller and tweaking it, I'm writing this from first principles, but I simply can't do that if I can't even grab the collision normals when I walk off a ledge.
     
    chusta likes this.
  12. jimroberts

    jimroberts

    Joined:
    Sep 4, 2014
    Posts:
    560
    Can you please post some debug information relating to the Collision object? Please include at least the following code.

    Code (csharp):
    1. void OnCollisionEnter(Collision other)
    2. {
    3.    if (other.contacts != null)
    4.    {
    5.      Debug.Log(other.contacts.Length);
    6.      for (int i = 0; i < other.contacts.Length; ++i)
    7.      {
    8.        Debug.Log(other.contacts[i].ToString());
    9.      }
    10.    }
    11.    else { Debug.Log("Contacts are null"); }
    12. }
     
    Last edited: Aug 4, 2016
  13. Rexor4321

    Rexor4321

    Joined:
    Sep 4, 2017
    Posts:
    3
    I had this problem as well, and neither this thread, nor any other, could help. My issue was solved simply by changing the type of collider. One of my objects had a capsule collider, and the other object destroyed itself on collision. It seems circle-colliders are more accurate than capsule-colliders, so the "OnCollisionEnter" in the first object returned zero contact-points.
     
  14. Mikael-H

    Mikael-H

    Joined:
    Apr 26, 2013
    Posts:
    263
    I just had this problem too, haven't seen this problem before so might be new for 2017.3. I only use circle colliders for my bullets and it seems like they sometimes do not have contact points in OnCollisionEnter2D. I have not seen this in 3D at all. I chose to ignore cases where they have no contact points. I am not sure f I am misunderstanding something or if this is a bug. Does a collision enter event without contact points make sense at all? Should this be possible? If not I can create a bug report.
     
  15. Raymoclaus

    Raymoclaus

    Joined:
    Aug 31, 2017
    Posts:
    1
    I thought I'd do my part and share my simple fix since this was the first result from googling this issue and the last bump was this year.
    Previously I would be accessing contacts like this:
    Code (CSharp):
    1. public void OnCollisionEnter2D(Collision2D collision)
    2. {
    3.     ContactPoint2D contact = collision.contacts[0];
    4. }
    I started getting the same error everyone here was receiving. I changed it to this:
    Code (CSharp):
    1. public void OnCollisionEnter2D(Collision2D collision)
    2. {
    3.     ContactPoint2D[] contact = new ContactPoint2D[1];
    4.     collision.GetContacts(contact);
    5. }
    Apparently, there were big changes to the underlying code with Unity, but I don't know exactly what the problem is. "contact" will be filled with contact points up to the size of the array or less depending on the number of contact points actually registered. Adjust the array size to something larger if you need multiple contact points or leave it at 1 if you just want the first registered contact point. Maybe increase the scope of "contact" to be a class variable and just use the second line so you aren't creating a new array every collision, but this is functional.
     
    shaderop and Mikael-H like this.