Created this Script for procedural dungeon generation, but wasn’t useful since separating rooms using this technique creates lot of issues while creating path between rooms. But hopefully this will help some one who wants to avoid overlapping rects.

 bool SteerSeparation()  
 {  
      bool noOverlap = true;  
      //_packs is a list of pack(object which contains rect object)
      // all the rects are at same position (0, 0)
      foreach (var pack in _packs)  
      {  
           foreach (var item in _packs)  
           {  
                if (pack.GetHashCode() != item.GetHashCode())  
                {  
                     while (pack.rect.Overlaps(item.rect))  
                     {  
                          Rect rect1 = pack.rect;  
                          Rect rect2 = item.rect;  
                          //create a geometric center between two rects
                          Rect geometricCenter = GetGeometricCenter(rect1, rect2);  
                          pack.rect = Steer(rect1, geometricCenter);  
                          item.rect = Steer(rect2, geometricCenter);  
                          noOverlap = false;  
                     }  
                }  
           }  
      }  
      return noOverlap;  
 }  
 Rect Steer(Rect rect, Rect geometricCenter)  
 {  
      Vector2 dir = new Vector2(rect.center.x - geometricCenter.center.x, rect.center.y - geometricCenter.center.y);  
      rect.center += dir * Time.deltaTime * 0.1f;  
      return rect;  
 }  
 private Rect GetGeometricCenter(Rect rect1, Rect rect2)  
 {  
      Rect rect = new Rect();  
      rect.x = Mathf.Min(rect1.x, rect2.x);  
      rect.y = Mathf.Min(rect1.y, rect2.y);  
      //calculate width  
      if (rect1.x < rect2.x)  
      {  
           if (rect2.x + rect2.width < rect1.x + rect1.width)  
           {  
                rect.width = rect1.width;  
           }  
           else  
           {  
                rect.width = rect1.x + rect1.width - rect2.x;  
           }  
      }  
      else if (rect1.x > rect2.x)  
      {  
           if (rect1.x + rect1.width < rect2.x + rect2.width)  
           {  
                rect.width = rect2.width;  
           }  
           else  
           {  
                rect.width = rect2.x + rect2.width - rect1.x;  
           }  
      }  
      else  
      {  
           rect.width = Mathf.Max(rect1.width, rect2.width);  
      }  
      //calculate height  
      if (rect1.y < rect2.y)  
      {  
           if (rect2.y + rect2.height < rect1.y + rect1.height)  
           {  
                rect.height = rect1.height;  
           }  
           else  
           {  
                rect.height = rect1.y + rect1.height - rect2.y;  
           }  
      }  
      else if (rect1.y > rect2.y)  
      {  
           if (rect1.y + rect1.height < rect2.y + rect2.height)  
           {  
                rect.height = rect2.height;  
           }  
           else  
           {  
                rect.height = rect2.y + rect2.height - rect1.y;  
           }  
      }  
      else  
      {  
           rect.height = Mathf.Max(rect1.height, rect2.height);  
      }  
      return rect;  
 }  

happy coding 🙂

Attach the below Script to an empty game object, and then apply the shader below to the material. I have created a plane from scratch for this to work as desired and easy to customize. The script that creates plane is also posted here.

The code is not explained in detail, if you have any difficulties please comment….

 using UnityEngine;  
 [RequireComponent (typeof(MeshFilter), typeof(MeshRenderer))]  
 public class FogOfWar : MonoBehaviour   
 {  
   Transform _player;  
   CustomPlane _plane;  
   Mesh _mesh;  
   public int explorerRangeX;  
   public int explorerRangeY;  
   TVec2<int> _lastExploredIndex;  
   void Awake()  
   {  
     _player = GameObject.FindGameObjectWithTag("Player").transform;  
     _mesh = GetComponent<MeshFilter>().mesh;  
     _mesh.Clear();  
     Events.instance.AddListener<GameEvent>(GenerateFogOfWar);  
   }  
   void GenerateFogOfWar(GameEvent e)  
   {  
     if (e.type == GameEvent.GENERATE_FOW)  
     {  
       Events.instance.RemoveListener<GameEvent>(GenerateFogOfWar);  
       _plane = new CustomPlane(e.width * e.gridSize, e.height * e.gridSize, (e.width * 8 / 512));  
       _mesh.vertices = _plane.getVertices();  
       _mesh.triangles = _plane.getTriangles();  
       _mesh.uv = _plane.getUVs();  
       _mesh.colors32 = _plane.getColors();  
       gameObject.transform.Translate(new Vector3(-_plane.width / 2, 0, -_plane.height / 2));  
       MeshCollider collider = gameObject.AddComponent<MeshCollider>();  
       collider.sharedMesh = _mesh;  
       _lastExploredIndex = new TVec2<int>(-1, -1);  
     }  
   }  
   void OnRenderObject()  
   {  
     Ray ray = new Ray(_player.position + Vector3.up * 20.0f, Vector3.down);  
     RaycastHit hitInfo;  
     if (Physics.Raycast(ray, out hitInfo, 5.0f))  
     {  
       Explore(gameObject.transform.InverseTransformPoint(hitInfo.point));  
     }  
   }  
   void UpdatePolygonColorAtIndex(int indexX, int indexY, int rangeX, int rangeY, byte alpha, bool isBorder = false)  
   {  
     for (int x = -rangeX; x <= rangeX; x++)  
     {  
       for (int y = -rangeY; y <= rangeY; y++)  
       {  
         if (isBorder)  
         {  
           if (x != -rangeX && x != rangeX && y != -rangeY && y != rangeY)  
           {  
             continue;  
           }  
         }  
         if (  
           _plane.isWithinRange((indexX + x), (indexY + y)) &&  
           _plane[indexX+x, indexY+y].getAlpha() > alpha)  
         {  
           _plane.UpdatePolygonColorAtIndex(indexX + x, indexY + y, new Color32(0, 0, 0, alpha));  
         }  
       }  
     }  
   }  
   void Explore(Vector3 position)  
   {  
     Vector2 quadIndex = _plane.GetPolygonIndexFromPosition(position);  
     int indexX = (int)quadIndex.x;  
     int indexY = (int)quadIndex.y;  
     if (_lastExploredIndex.x == indexX && _lastExploredIndex.y == indexY)  
     {  
       //don't update  
     }  
     else  
     {  
       UpdatePolygonColorAtIndex(indexX, indexY, explorerRangeX + 1, explorerRangeY + 1, 64, true);  
       UpdatePolygonColorAtIndex(indexX, indexY, explorerRangeX, explorerRangeY, 0, false);  
       UpdatePolygonColorAtIndex(indexX, indexY, explorerRangeX + 3, explorerRangeY, 64, true);  
       UpdatePolygonColorAtIndex(indexX, indexY, explorerRangeX + 2, explorerRangeY - 1, 0, false);  
       UpdatePolygonColorAtIndex(indexX, indexY, explorerRangeX, explorerRangeY + 2, 64, true);  
       UpdatePolygonColorAtIndex(indexX, indexY, explorerRangeX - 1, explorerRangeY + 1, 0, false);  
       _mesh.colors32 = _plane.getColors();  
       _lastExploredIndex.Set(indexX, indexY);  
     }  
   }  
 }  

Shader Code
:

 Shader "Custom/VertexAlphaFow"  
 {  
      Properties  
      {  
           _Color("Color", Color) = (1,1,1,1)  
           _MainTex("Base Albedo (RGB)", 2D) = "white" {}  
      }  
      SubShader  
      {  
           Tags{ "Queue" = "Transparent" "IgnoreProjector" = "True" "RenderType" = "Transparent" }  
           Blend SrcAlpha OneMinusSrcAlpha  
           pass  
           {  
                CGPROGRAM  
                #pragma fragmentoption ARB_precision_hint_fastest  
                #pragma vertex vert  
                #pragma fragment frag  
                #include "UnityCG.cginc"  
                #pragma target 3.0  
                uniform sampler2D _MainTex;  
                struct Vertex  
                {  
                     float4 vertex : POSITION;  
                     float4 color : COLOR;  
                     float4 texCoord : TEXCOORD0;  
                };  
                struct Fragment  
                {  
                     float4 pos : SV_POSITION;  
                     half4 color : COLOR;  
                     half2 uv : TEXCOORD0;  
                };  
                Fragment vert(Vertex i)  
                {  
                     Fragment fragOut;  
                     fragOut.color = i.color;  
                     fragOut.pos = mul(UNITY_MATRIX_MVP, i.vertex);  
                     fragOut.uv = i.texCoord;  
                     return fragOut;  
                }  
                half4 frag(Fragment i) : COLOR  
                {  
                     //in case want a tex  
                     //return half4(tex2D(_MainTex, i.uv).rgb, i.color.a);  
                     //use vertex color  
                     return i.color;  
                }  
                ENDCG  
           }  
      }  
           FallBack "VertexLit"  
 }  

Custom Plane Script

 using UnityEngine;  
 using System.Collections.Generic;  
 public class CustomPlane  
 {  
   private Polygon[,] _polygons;  
   public Polygon this[int x, int y]  
   {  
     get  
     {  
       return _polygons[x, y];  
     }  
   }  
   private int _quadSize;  
   public int quadSize  
   {  
     get  
     {  
       return _quadSize;  
     }  
     set  
     {  
       _quadSize = value;  
     }  
   }  
   private int _width;  
   public int width  
   {  
     get  
     {  
       return _width;  
     }  
     set  
     {  
       _width = value;  
     }  
   }  
   private int _height;  
   public int height  
   {  
     get  
     {  
       return _height;  
     }  
     set  
     {  
       _height = value;  
     }  
   }  
   private List<Vector3> _vertices;  
   private List<Vector2> _uvs;  
   private List<int> _triangles;  
   private List<Color32> _colors;  
   public CustomPlane(int width, int height, int quadSize)  
   {  
     _quadSize = quadSize;  
     _width = width;  
     _height = height;  
     _vertices = new List<Vector3>();  
     _triangles = new List<int>();  
     _uvs = new List<Vector2>();  
     _colors = new List<Color32>();  
     int row = Mathf.CeilToInt(_width / _quadSize);  
     int col = Mathf.CeilToInt(_height / _quadSize);  
     _polygons = new Polygon[row, col];  
     int runningIndex = -1;  
     for (int x = 0; x < row; x++)  
     {  
       for (int y = 0; y < col; y++)  
       {  
         int lastRunningIndex = runningIndex;  
         Vertex bottomLeft = (x - 1 > -1) ? _polygons[x - 1, y].bottomRight : (y - 1 > -1) ? _polygons[x, y - 1].topLeft : Polygon.getNode("bl", x, y, quadSize, ++runningIndex);  
         if (lastRunningIndex != runningIndex)  
         {  
           _vertices.Add(bottomLeft.position);  
         }  
         lastRunningIndex = runningIndex;  
         Vertex topLeft = (x - 1 > -1) ? _polygons[x - 1, y].topRight : Polygon.getNode("tl", x, y, quadSize, ++runningIndex);  
         if (lastRunningIndex != runningIndex)  
         {  
           _vertices.Add(topLeft.position);  
         }  
         lastRunningIndex = runningIndex;  
         Vertex topRight = Polygon.getNode("tr", x, y, quadSize, ++runningIndex);  
         if (lastRunningIndex != runningIndex)  
         {  
           _vertices.Add(topRight.position);  
         }  
         lastRunningIndex = runningIndex;  
         Vertex bottomRight = (y - 1 > -1) ? _polygons[x, y - 1].topRight : Polygon.getNode("br", x, y, quadSize, ++runningIndex);  
         if (lastRunningIndex != runningIndex)  
         {  
           _vertices.Add(bottomRight.position);  
         }  
         _polygons[x, y] = new Polygon(bottomLeft, topLeft, topRight, bottomRight, new Color32(0, 0, 0, 255));  
         _triangles.Add(bottomLeft.index);  
         _triangles.Add(topLeft.index);  
         _triangles.Add(topRight.index);  
         _triangles.Add(bottomRight.index);  
         _triangles.Add(bottomLeft.index);  
         _triangles.Add(topRight.index);  
       }  
     }  
     //generate uv's & color  
     int length = _vertices.Count;  
     for (int index = 0; index < length; index++)  
     {  
       _uvs.Add(  
             new Vector2(  
                 Mathf.InverseLerp(0, _width, _vertices[index].x),  
                 Mathf.InverseLerp(0, _height, _vertices[index].z)  
               )  
         );  
       _colors.Add(new Color32(0, 0, 0, 128));  
     }  
   }  
   public Vector3[] getVertices()  
   {  
     return _vertices.ToArray();  
   }  
   public int[] getTriangles()  
   {  
     return _triangles.ToArray();  
   }  
   public Vector2[] getUVs()  
   {  
     return _uvs.ToArray();  
   }  
   public Color32[] getColors()  
   {  
     return _colors.ToArray();  
   }  
   public Vector2 GetPolygonIndexFromTexCoord(Vector2 texCoord)  
   {  
     int xIndex, yIndex = 0;  
     xIndex = Mathf.CeilToInt((texCoord.x * _width) / _quadSize);  
     yIndex = Mathf.CeilToInt((texCoord.y * _height) / _quadSize);  
     return new Vector2(xIndex, yIndex);  
   }  
   public Vector2 GetPolygonIndexFromPosition(Vector3 position)  
   {  
     int xIndex, yIndex = 0;  
     xIndex = Mathf.FloorToInt(position.x / _quadSize);  
     yIndex = Mathf.FloorToInt(position.z / _quadSize);  
     return new Vector2(xIndex, yIndex);  
   }  
   private void UpdateColorAt(int vertexIndex, Color32 color)  
   {  
     _colors[vertexIndex] = color;  
   }  
   public bool isWithinRange(int x, int y)  
   {  
     return ((x >= 0 && x < _polygons.GetLength(0)) && (y >= 0 && y < _polygons.GetLength(1)));  
   }  
   public void UpdatePolygonColorAtIndex(int x, int y, Color32 color)  
   {  
     Polygon poly = _polygons[x, y];  
     //update polygon data  
     poly.UpdateColor(color);  
     //update render data from updated polygon  
     UpdateColorAt(poly.bottomLeft.index, color);  
     UpdateColorAt(poly.topLeft.index, color);  
     UpdateColorAt(poly.topRight.index, color);  
     UpdateColorAt(poly.bottomRight.index, color);  
   }  
 }  

Happy Coding 🙂