Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.

Check if 2 RectTransforms overlapping?

Discussion in 'Scripting' started by IgorAherne, Feb 4, 2018.

  1. IgorAherne

    IgorAherne

    Joined:
    May 15, 2013
    Posts:
    386
    I struggled to find a fairly decent "are 2 rectTransforms overlapping" post, so here is the code I came up with.

    It requires your canvas to be in the Camera-space.
    The nice thing about it, is the camera doesn't have to be aligned with coordinate axis, and the script will still detect overlap of Rect transforms.

    However, rect transforms shouldn't be rotated within the canvas itself.

    Also, you could use it to check if the UI element goes offscreen.

    Code (CSharp):
    1.   //if your viewport is screen, then keep it as 'null'
    2.     // NOTICE - doesn't consider if the rectangles are rotating,
    3.     //
    4.     // but shoudl work even if canvas's camera ISN'T aligned with world axis :)
    5.     public static bool is_rectTransformsOverlap( Camera cam,
    6.                                                  RectTransform elem,
    7.                                                  RectTransform viewport = null ){
    8.         Vector2 viewportMinCorner;
    9.         Vector2 viewportMaxCorner;
    10.  
    11.         if(viewport != null) {
    12.             //so that we don't have to traverse the entire parent hierarchy (just to get screen coords relative to screen),
    13.             //ask the camera to do it for us.
    14.             //first get world corners of our rect:
    15.             Vector3[] v_wcorners = new Vector3[4];
    16.             viewport.GetWorldCorners(v_wcorners); //bot left, top left, top right, bot right
    17.  
    18.             //+ow shove it back into screen space. Now the rect is relative to the bottom left corner of screen:
    19.             viewportMinCorner = cam.WorldToScreenPoint(v_wcorners[0]);
    20.             viewportMaxCorner = cam.WorldToScreenPoint(v_wcorners[2]);
    21.         }
    22.         else {
    23.             //just use the scren as the viewport
    24.             viewportMinCorner = new Vector2( 0, 0 );
    25.             viewportMaxCorner = new Vector2( Screen.width, Screen.height);
    26.         }
    27.  
    28.         //give 1 pixel border to avoid numeric issues:
    29.         viewportMinCorner += Vector2.one;
    30.         viewportMaxCorner -= Vector2.one;
    31.  
    32.         //do a similar procedure, to get the "element's" corners relative to screen:
    33.         Vector3[] e_wcorners = new Vector3[4];
    34.         elem.GetWorldCorners(e_wcorners);
    35.  
    36.         Vector2 elem_minCorner = cam.WorldToScreenPoint(e_wcorners[0]);
    37.         Vector2 elem_maxCorner = cam.WorldToScreenPoint(e_wcorners[2]);
    38.  
    39.         //perform comparison:
    40.         if(elem_minCorner.x > viewportMaxCorner.x) { return false; }//completelly outside (to the right)
    41.         if(elem_minCorner.y > viewportMaxCorner.y) { return false; }//completelly outside (is above)
    42.  
    43.         if(elem_maxCorner.x < viewportMinCorner.x) {  return false;  }//completelly outside (to the left)
    44.         if(elem_maxCorner.y < viewportMinCorner.y) {  return false;  }//completelly outside (is below)
    45.  
    46.         /*
    47.              commented out, but use it if need to check if element is completely inside:
    48.             Vector2 minDif = viewportMinCorner - elem_minCorner;
    49.             Vector2 maxDif = viewportMaxCorner - elem_maxCorner;
    50.             if(minDif.x < 0  &&  minDif.y < 0  &&  maxDif.x > 0  &&maxDif.y > 0) { //return "is completely inside" }
    51.         */
    52.      
    53.         return true;//passed all checks, is inside (at least partially)
    54.     }
    55.  
     
  2. Laperen

    Laperen

    Joined:
    Feb 1, 2016
    Posts:
    1,065
    you could use RectTransform.GetLocalCorners() instead of the camera trickery I think.
     
  3. IgorAherne

    IgorAherne

    Joined:
    May 15, 2013
    Posts:
    386
    The result will be 4 coordinates but relative to the parent an the hierarchy might be very deep.
    My code allows to compare RectTransform that don't share the same parent.
     
    Last edited: Apr 1, 2018
    Oddness likes this.
  4. StartStart

    StartStart

    Joined:
    Jan 2, 2013
    Posts:
    150
    Your code is working fine. Thanks!
     
  5. sampenguin

    sampenguin

    Joined:
    Feb 1, 2011
    Posts:
    64
    Thank you so much for this!! I tried like 4 implementations for a drag and drop based on RectTransforms that ALMOST worked, before your type of approach worked perfectly. Seems ridiculous that comparing Rect world position values is still such a PITA, this should be encapsulated inside a standard RectTransform static method!
     
    IgorAherne likes this.