Search Unity

ColliderCast and IsTouching Help

Discussion in 'Physics' started by SorneBachse, Jan 15, 2020.

  1. SorneBachse

    SorneBachse

    Joined:
    Dec 27, 2012
    Posts:
    62
    Hey everyone.

    I'm currently having issues with my units getting stuck inside each other. The way it's currently working is that I'm using a collider cast to check if I'm moving into a unit, and if so, don't move any more.

    Code (CSharp):
    1.  
    2.         if (!ColliderCast(physicalCollider, Movement, settings.UnitColliderFilter, out RaycastHit2D hit, 0.5f))
    3.         {
    4.             body.MovePosition(body.position + Movement * Time.fixedDeltaTime);
    5.         }
    And this is the ColliderCast function:

    Code (CSharp):
    1.     public bool ColliderCast(Collider2D collider, Vector2 direction, ContactFilter2D filter, out RaycastHit2D hit, float length = 0.2f)
    2.     {
    3.         int numHits = collider.Cast(direction.normalized, filter, colliderCastHits, length);
    4.         CircleCollider2D myCol = collider as CircleCollider2D;
    5.  
    6.         IMDraw.WireSphere3D((Vector2)transform.position + myCol.offset + (direction.normalized * length), myCol.radius, Color.white);
    7.  
    8.         for (int i = 0; i < numHits; i++)
    9.         {
    10.             hit = colliderCastHits[i];
    11.  
    12.             if (!hit.collider.isTrigger)
    13.             {
    14.                 //Collision
    15.                 Debug.Log("Colliding with " + hit.collider.transform.root.name, hit.collider);
    16.                 Debug.Log("Is overlapping " + myCol.IsTouching(hit.collider));
    17.  
    18.                 return true;
    19.             }
    20.         }
    21.  
    22.         //No collision
    23.         hit = new RaycastHit2D();
    24.         return false;
    25.     }
    Here's a gif showcasing the problem:

    https://i.imgur.com/GDuGUMM.gif

    As you can see, the two green colliders are stuck inside each other. The white colliders are where I'm ColliderCasting to. This is where I'm confused, since it doesn't seem to overlap.

    I read on the docs (https://docs.unity3d.com/ScriptReference/Collider2D.Cast.html) that if you use collider.Cast() with colliders already inside each other from the start of the cast, it will count as a hit. So I thought I could use collider.IsTouching() to determine when colliders are overlapping from the start, but that simply returns false. What am I doing wrong here?

    Thanks in advance.
     
  2. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,459
    You're casting in the direction but only a distance of a constant "0.5". You should be casting a distance of the intended movement which in your case is "Movement * Time.fixedDeltaTime)".

    Also, you can filter out triggers with the ContactFilter2D to save checking that.

    IsTouching only works if there's an actual contact active, it doesn't perform an overlap check or anything. As long as you're only using MovePosition and not repositoning directly then you'll have a contact.
     
    SorneBachse likes this.
  3. SorneBachse

    SorneBachse

    Joined:
    Dec 27, 2012
    Posts:
    62
    Hey, thanks for the quick reply.

    So, I tried adding all your suggestions like so:


    Code (CSharp):
    1.  
    2.         if (!ColliderCast(physicalCollider, Movement * Time.fixedDeltaTime, settings.UnitColliderFilter, out RaycastHit2D hit))
    3.         {
    4.             body.MovePosition(body.position + Movement * Time.fixedDeltaTime);
    5.         }
    6.  
    Code (CSharp):
    1.  
    2.     public bool ColliderCast(Collider2D collider, Vector2 direction, ContactFilter2D filter, out RaycastHit2D hit)
    3.     {
    4.         int numHits = collider.Cast(direction, filter, colliderCastHits, direction.magnitude);
    5.         CircleCollider2D myCol = collider as CircleCollider2D;
    6.  
    7.         IMDraw.WireSphere3D((Vector2)myCol.transform.position + myCol.offset + direction, myCol.radius, Color.white);
    8.  
    9.         for (int i = 0; i < numHits; i++)
    10.         {
    11.             //Collision
    12.             Debug.Log("Colliding with " + hit.collider.transform.root.name, hit.collider);
    13.             Debug.Log("Is overlapping " + myCol.IsTouching(hit.collider));
    14.  
    15.             Debug.DrawLine((Vector2)myCol.transform.position + myCol.offset, hit.collider.transform.position);
    16.  
    17.             return true;
    18.         }
    19.  
    20.         //No collision
    21.         hit = new RaycastHit2D();
    22.         return false;
    23.     }
    But they still get stuck inside each other for some reason:
    https://i.imgur.com/VQzoa4P.gif

    EDIT: Actually nevermind.. I got it to work now.
    Looks like I had some layers setup wrong in the Phyics2D Collision Matrix, causing them to not collide with each other to begin with. Sorry!

    Thanks for the help though.
     
    Last edited: Jan 15, 2020
    MelvMay likes this.