public static void InstantiatePrefabs(TileLayer layer)
    {
        if(layer.tileset == null) return;
        if(layer.tileset.tiles == null) return;

        Transform t = layer.transform.FindChild("TileInstances");
        if(t!=null) {
            DestroyImmediate(t.gameObject);
        }
        t = layer.transform.FindChild("BoxColliders");
        if(t!=null) {
            DestroyImmediate(t.gameObject);
        }

        GameObject instances = new GameObject("TileInstances");
        Transform instancesTransform = instances.transform;
        instancesTransform.parent = layer.transform;
        instancesTransform.localPosition = new Vector3(0, 0, 0);
        instancesTransform.localScale = new Vector3(1, 1, 1);
        instancesTransform.localRotation = new Quaternion(0,0,0,0);

        GameObject boxes = new GameObject("BoxColliders");
        Transform boxesTransform = boxes.transform;
        boxesTransform.parent = layer.transform;
        boxesTransform.localPosition = new Vector3(0, 0, 0);
        boxesTransform.localScale = new Vector3(1, 1, 1);
        boxesTransform.localRotation = new Quaternion(0,0,0,0);

        GameObject prefab;
        GameObject instance;
        GameObject box;
        BoxCollider2D collider;
        Hashtable skip = new Hashtable();

        if(layer.tileSpacing == new Vector2(-1,-1) || layer.tileSpacing == new Vector2(0,0)) layer.tileSpacing = layer.tileSize;

        for(int i = 0; i < layer.layerSize.x; i++) {
            for(int j = 0; j < layer.layerSize.y; j++) {
                UniTileTile tile = layer.GetTile(i, j);
                if(tile!=null) {
                    TileInstance inst = layer.GetTileData(i, j);
                    prefab = tile.prefab;
                    if(prefab != null) {
        #if (UNITY_3_5 || UNITY_3_6 || UNITY_3_7 || UNITY_3_8 || UNITY_3_9)
                        instance = (GameObject)PrefabUtility.InstantiatePrefab(prefab);
        #else
                        instance = (GameObject)PrefabUtility.InstantiatePrefab(prefab);
        #endif
                        Vector3 scale = instance.transform.localScale;
                        instance.transform.parent = instancesTransform;
                        instance.transform.localScale = scale;
                        Quaternion q = new Quaternion(0,0,0,0);
                        q.eulerAngles = new Vector3(0, 0, (int)inst.rotation * 90);
                        instance.transform.localRotation = q;
                        instance.transform.localPosition = (Vector3)TileLayerUtil.TransformPoint(new Vector2(i * layer.tileSpacing.x + tile.prefabOffset.x, j * layer.tileSpacing.y + tile.prefabOffset.y), new Vector2(i * layer.tileSpacing.x + layer.tileSpacing.x / 2f, j * layer.tileSpacing.y +  + layer.tileSpacing.y / 2f), inst.flippedHorizontally, inst.flippedVertically, inst.rotation);
                        if(inst.flippedHorizontally) {
                            instance.transform.localScale = new Vector3(-instance.transform.localScale.x, instance.transform.localScale.y, instance.transform.localScale.z);
                        }
                        if(inst.flippedVertically) {
                            instance.transform.localScale = new Vector3(instance.transform.localScale.x, -instance.transform.localScale.y, instance.transform.localScale.z);
                        }
                    }
                    if(layer.collidable && tile.boxCollider) {
                        if(skip[new Vector2(i, j)] == null) {
                            if(tile.boxPrefab!=null)
        #if (UNITY_3_5 || UNITY_3_6 || UNITY_3_7 || UNITY_3_8 || UNITY_3_9)
                                box = (GameObject)PrefabUtility.InstantiatePrefab(tile.boxPrefab);
        #else
                                box = (GameObject)PrefabUtility.InstantiatePrefab(tile.boxPrefab);
        #endif
                            else
                                box = new GameObject("BoxCollider");

                            box.layer = tile.boxLayer;
                            box.tag = tile.boxTag;
                            collider = box.GetComponent<BoxCollider2D>();
                            if(!collider) collider = box.AddComponent<BoxCollider2D>();
                            collider.sharedMaterial = tile.boxMaterial;
                            box.transform.parent = boxesTransform;
                            box.transform.localScale = new Vector3(1, 1, 1);
                            box.transform.localRotation = new Quaternion(0,0,0,0);
                            box.transform.localPosition = new Vector3(i * layer.tileSpacing.x, j * layer.tileSpacing.y, 0);

                            int sizeX = 1;
                            int sizeY = 1;
                            while(skip[new Vector2(i, j + sizeY)]==null && layer.CanMergeBoxColliders(i, j, i, j+sizeY)) {
                                skip[new Vector2(i, j + sizeY)] = true;
                                sizeY++;
                            }

                            if(sizeY == 1) {
                                while(skip[new Vector2(i + sizeX, j)]==null && layer.CanMergeBoxColliders(i, j, i+sizeX, j)) {
                                    skip[new Vector2(i + sizeX, j)] = true;
                                    sizeX++;
                                }
                            } else {
                                sizeX = 1;
                                bool columnOk = true;
                                int column = 1;
                                while(columnOk) {
                                    columnOk = true;
                                    for(int k=0;k<sizeY;k++) {
                                        if(skip[new Vector2(i + column, j + k)]!=null || !layer.CanMergeBoxColliders(i,j,i+column, j+k)) {
                                            columnOk = false;
                                            break;
                                        }
                                    }
                                    if(columnOk) {
                                        column++;
                                    }
                                }
                                sizeX = column;
                                for(int k=0;k<sizeX;k++) {
                                    for(int l=0;l<sizeY;l++) {
                                        skip[new Vector2(i + k, j + l)] = true;
                                    }
                                }
                            }

                            if(tile.customBoxDimensions) {
                                Rect rect = TileLayerUtil.TransformRect(tile.boxDimensions, layer.tileSize / 2f, inst.flippedHorizontally, inst.flippedVertically, inst.rotation);
                                float x = rect.width;
                                float y = rect.height;
                                if(rect.x == 0 && rect.xMax == layer.tileSpacing.x) {
                                    x = layer.tileSpacing.x * sizeX;
                                }
                                if(rect.y == 0 && rect.yMax == layer.tileSpacing.y) {
                                    y = layer.tileSpacing.y * sizeY;
                                }
                                collider.size = new Vector3(x, y, tile.boxDepth);
                                collider.offset = new Vector3(collider.size.x / 2f + rect.x, collider.size.y / 2f + rect.y);
                            } else {
                                collider.size = new Vector3(layer.tileSpacing.x * sizeX, layer.tileSpacing.y * sizeY, tile.boxDepth);
                                collider.offset = new Vector3(collider.size.x / 2f, collider.size.y / 2f);
                                //collider.center = new Vector3(layer.tileSpacing.x * sizeX / 2f, layer.tileSpacing.y * sizeY / 2f);
                            }

                        }
                    }
                }
            }
        }
Exemplo n.º 2
0
/*
 *      public static void RedrawGroupForTiles(TileLayer layer, TilePos[] tiles)
 *      {
 *              List<GroupPos> groups = new List<GroupPos>();
 *              foreach(TilePos tile in tiles)
 *              {
 *                      GroupPos group = TileToGroup(layer, tile);
 *                      if(!groups.Contains(group))
 *                              groups.Add(group);
 *              }
 *
 *              foreach(GroupPos group in groups)
 *              {
 *                      RedrawGroup(layer, group.x, group.y);
 *              }
 *      }
 */

    public static void RedrawGroup(TileLayer layer, int groupX, int groupY)
    {
        if (layer == null)
        {
            return;
        }
        if (layer.parent != null)
        {
            layer = layer.parent;
        }

        GameObject g;
        Transform  t = layer.GroupRoot.FindChild("group_" + groupX + "_" + groupY);
        Mesh       m;

        if (t == null)
        {
            g = new GameObject("group_" + groupX + "_" + groupY);
            t = g.transform;
            t.transform.parent = layer.GroupRoot;
            t.localPosition    = new Vector3(groupX * layer.tileSpacing.x * layer.groupSize.x, groupY * layer.tileSpacing.y * layer.groupSize.y);
            t.localScale       = new Vector3(1, 1, 1);
            Quaternion quaternion = t.localRotation;
            quaternion.eulerAngles = new Vector3(0, 0, 0);
            t.localRotation        = quaternion;
            MeshRenderer r = g.AddComponent <MeshRenderer>();
            MeshFilter   f = g.AddComponent <MeshFilter>();
            m          = f.sharedMesh = new Mesh();
            r.material = layer.material;
        }
        else
        {
            g = t.gameObject;
            MeshFilter f = t.GetComponent <MeshFilter>();
            GameObject.DestroyImmediate(f.sharedMesh);;
            m = f.sharedMesh = new Mesh();
        }

        //ArrayList temp = new ArrayList();
        List <Hashtable> temp = new List <Hashtable>();

        List <TileLayer> layers = new List <TileLayer>();

        layers.Add(layer);
        for (int i = 0; i < layer.transform.childCount; i++)
        {
            TileLayer child = layer.transform.GetChild(i).GetComponent <TileLayer>();
            if (child != null)
            {
                layers.Add(child);
            }
        }

        layers.Sort(delegate(TileLayer l1, TileLayer l2)
                    { return((l2 == layer?0f:l2.transform.localPosition.z).CompareTo(l1 == layer?0f:l1.transform.localPosition.z)); });

        for (int c = 0; c < layers.Count; c++)
        {
            TileLayer lyr = layers[c];

            Hashtable skip = new Hashtable();


            for (int i = groupX * (int)lyr.groupSize.x; i < Mathf.Min(lyr.layerSize.x, groupX * (int)lyr.groupSize.x + lyr.groupSize.x); i++)
            {
                for (int j = groupY * (int)lyr.groupSize.y; j < Mathf.Min(lyr.layerSize.y, groupY * (int)lyr.groupSize.y + lyr.groupSize.y); j++)
                {
                    UniTileTile  tile = lyr.GetTile(i, j);
                    TileInstance data = lyr.GetTileData(i, j);
                    if (data != null && data.id != -1)
                    {
                        if (skip[new Vector2(i, j)] == null)
                        {
                            Hashtable h = new Hashtable();
                            h["x"]         = i;
                            h["y"]         = j;
                            h["z"]         = (lyr == layer?0:lyr.transform.localPosition.z);
                            h["tile"]      = data;
                            h["resizable"] = tile.resizable;

                            int sizeX = 1;
                            int sizeY = 1;

                            if (tile != null && tile.resizable)
                            {
                                while (skip[new Vector2(i, j + sizeY)] == null && lyr.GetTileId(i, j + sizeY) == data.id && j + sizeY < (groupY + 1) * lyr.groupSize.y)
                                {
                                    skip[new Vector2(i, j + sizeY)] = true;
                                    sizeY++;
                                }

                                if (sizeY == 1)
                                {
                                    while (skip[new Vector2(i + sizeX, j)] == null && lyr.GetTileId(i + sizeX, j) == data.id && i + sizeX < (groupX + 1) * lyr.groupSize.x)
                                    {
                                        skip[new Vector2(i + sizeX, j)] = true;
                                        sizeX++;
                                    }
                                }
                                else
                                {
                                    sizeX = 1;
                                    bool columnOk = true;
                                    int  column   = 1;
                                    while (columnOk && i + column < (groupX + 1) * lyr.groupSize.x)
                                    {
                                        columnOk = true;
                                        for (int k = 0; k < sizeY; k++)
                                        {
                                            if (skip[new Vector2(i + column, j + k)] != null || lyr.GetTileId(i + column, j + k) != data.id)
                                            {
                                                columnOk = false;
                                                break;
                                            }
                                        }
                                        if (columnOk)
                                        {
                                            column++;
                                        }
                                    }
                                    sizeX = column;
                                    for (int k = 0; k < sizeX; k++)
                                    {
                                        for (int l = 0; l < sizeY; l++)
                                        {
                                            skip[new Vector2(i + k, j + l)] = true;
                                        }
                                    }
                                }
                            }

                            h["sizeX"] = sizeX;
                            h["sizeY"] = sizeY;

                            temp.Add(h);
                        }
                    }
                }
            }
        }

        if (temp.Count == 0)
        {
            GameObject.DestroyImmediate(m);
            GameObject.DestroyImmediate(g);
        }
        else
        {
            Vector3 [] vertices  = new Vector3[4 * temp.Count];
            int []     triangles = new int[6 * temp.Count];
            Vector2 [] uv        = new Vector2[4 * temp.Count];

            for (int i = 0; i < temp.Count; i++)
            {
                Hashtable    h     = temp[i] as Hashtable;
                int          x     = (int)((int)h["x"] * layer.tileSpacing.x) - (int)(groupX * layer.tileSpacing.x * layer.groupSize.x);
                int          y     = (int)((int)h["y"] * layer.tileSpacing.y) - (int)(groupY * layer.tileSpacing.y * layer.groupSize.y);
                int          sizeX = (int)h["sizeX"];
                int          sizeY = (int)h["sizeY"];
                TileInstance data  = (TileInstance)h["tile"];

                Rect vRect  = new Rect();
                Rect uvRect = new Rect();

                int columns = (int)((layer.material.mainTexture.width) / (layer.tileSize.x + layer.borderSize.x * 2));

                if (sizeX == 1 && sizeY == 1)
                {
                    vRect.x    = (int)x - layer.overlap.x;
                    vRect.y    = (int)y - layer.overlap.y;
                    vRect.xMax = layer.tileSpacing.x + (int)x + layer.overlap.x;
                    vRect.yMax = layer.tileSpacing.y + (int)y + layer.overlap.y;

                    uvRect.x      = Mathf.Floor(data.id % columns) * (layer.tileSize.x + layer.borderSize.x * 2f) + layer.borderSize.x - layer.overlap.x;
                    uvRect.y      = layer.material.mainTexture.height - (Mathf.Floor(data.id / columns) * (layer.tileSize.x + layer.borderSize.y * 2f) + layer.borderSize.y + layer.overlap.y + layer.tileSize.y);
                    uvRect.width  = layer.tileSize.x + layer.overlap.x;
                    uvRect.height = layer.tileSize.y + layer.overlap.y;

                    Texture2D texture = (Texture2D)layer.material.mainTexture;

                    if (layer.readableTexture && !Application.isPlaying)
                    {
                        try {
                            // Find empty columns left
                            int start = Mathf.Max(0, (int)Mathf.Round(uvRect.x));
                            int end   = Mathf.Min(texture.width, (int)Mathf.Round(uvRect.xMax));
                            for (int j = start; j < end; j++)
                            {
                                int     min      = Mathf.Max(0, (int)Mathf.Round(uvRect.y));
                                int     max      = Mathf.Min(texture.height - min, (int)Mathf.Round(uvRect.height));
                                Color[] pixels   = texture.GetPixels(j, min, 1, max);
                                bool    allTrans = true;
                                for (int k = 0; k < pixels.Length; k++)
                                {
                                    if (pixels[k].a != 0)
                                    {
                                        allTrans = false;
                                        break;
                                    }
                                }

                                if (!allTrans)
                                {
                                    break;
                                }

                                uvRect.xMin++;
                                vRect.xMin += layer.tileSpacing.x / layer.tileSize.x;
                            }

                            // Find empty columns right
                            start = Mathf.Min(texture.width, (int)Mathf.Round(uvRect.xMax)) - 1;
                            end   = Mathf.Max(0, (int)Mathf.Round(uvRect.x));
                            for (int j = start; j >= end; j--)
                            {
                                int     min      = Mathf.Max(0, (int)Mathf.Round(uvRect.y));
                                int     max      = Mathf.Min(texture.height - min, (int)Mathf.Round(uvRect.height));
                                Color[] pixels   = texture.GetPixels(j, min, 1, max);
                                bool    allTrans = true;
                                for (int k = 0; k < pixels.Length; k++)
                                {
                                    if (pixels[k].a != 0)
                                    {
                                        allTrans = false;
                                        break;
                                    }
                                }
                                if (!allTrans)
                                {
                                    break;
                                }
                                else
                                {
                                    uvRect.xMax--;
                                    vRect.xMax -= layer.tileSpacing.x / layer.tileSize.x;
                                }
                            }

                            // Find empty rows down
                            start = Mathf.Max(0, (int)Mathf.Round(uvRect.y));
                            end   = Mathf.Min(texture.height, (int)Mathf.Round(uvRect.yMax));
                            for (int j = start; j < end; j++)
                            {
                                int min = Mathf.Max(0, (int)Mathf.Round(uvRect.x));
                                int max = Mathf.Min(texture.width - min, (int)Mathf.Round(uvRect.width));

                                Color[] pixels   = texture.GetPixels(min, j, max, 1);
                                bool    allTrans = true;
                                for (int k = 0; k < pixels.Length; k++)
                                {
                                    if (pixels[k].a != 0)
                                    {
                                        allTrans = false;
                                        break;
                                    }
                                }

                                if (!allTrans)
                                {
                                    break;
                                }

                                uvRect.yMin++;
                                vRect.yMin += layer.tileSpacing.y / layer.tileSize.y;
                            }

                            // Find empty rows up
                            start = Mathf.Min(texture.height, (int)Mathf.Round(uvRect.yMax)) - 1;
                            end   = Mathf.Max(0, (int)Mathf.Round(uvRect.y));

                            for (int j = start; j >= end; j--)
                            {
                                int     min      = Mathf.Max(0, (int)Mathf.Round(uvRect.x));
                                int     max      = Mathf.Min(texture.width - min, (int)Mathf.Round(uvRect.width));
                                Color[] pixels   = texture.GetPixels(min, j, max, 1);
                                bool    allTrans = true;
                                for (int k = 0; k < pixels.Length; k++)
                                {
                                    if (pixels[k].a != 0)
                                    {
                                        allTrans = false;
                                        break;
                                    }
                                }

                                if (!allTrans)
                                {
                                    break;
                                }
                                uvRect.yMax--;
                                vRect.yMax -= layer.tileSpacing.y / layer.tileSize.y;
                            }
                        } catch {
                            layer.readableTexture = false;
                        }
                    }
                }
                else
                {
                    vRect.x    = (int)x - layer.overlap.x;
                    vRect.y    = (int)y - layer.overlap.y;
                    vRect.xMax = layer.tileSpacing.x * (float)sizeX + (int)x + layer.overlap.x;
                    vRect.yMax = layer.tileSpacing.y * (float)sizeY + (int)y + layer.overlap.y;

                    //vRect.xMax = layer.tileSize.x * 1 + (int)x  + layer.overlap.x;
                    //vRect.yMax = layer.tileSize.y * 1 + (int)y + layer.overlap.y;

                    uvRect.x      = Mathf.Floor(data.id % columns) * (layer.tileSize.x + layer.borderSize.x * 2f) + (layer.borderSize.x - layer.overlap.x) / sizeX + 1;
                    uvRect.y      = layer.material.mainTexture.height - (Mathf.Floor(data.id / columns) * (layer.tileSize.x + layer.borderSize.y * 2f) + (layer.borderSize.y + layer.overlap.y) / sizeY + layer.tileSize.y) + 1;
                    uvRect.width  = layer.tileSize.x + layer.overlap.x - 2;
                    uvRect.height = layer.tileSize.y + layer.overlap.y - 2;
                }



                Vector2 center = new Vector2(x, y) + layer.tileSpacing / 2f;

                //Vecrtices
                vertices[(i * 4) + 0] = new Vector3(vRect.x, vRect.yMax, (float)h["z"]);
                vertices[(i * 4) + 1] = new Vector3(vRect.xMax, vRect.yMax, (float)h["z"]);
                vertices[(i * 4) + 2] = new Vector3(vRect.x, vRect.y, (float)h["z"]);
                vertices[(i * 4) + 3] = new Vector3(vRect.xMax, vRect.y, (float)h["z"]);

                bool reversed = false;

                if (!(bool)h["resizable"])
                {
                    for (int j = 0; j < (uint)data.rotation; j++)
                    {
                        vertices[(i * 4) + 0] = RotatePoint(vertices[(i * 4) + 0], center);
                        vertices[(i * 4) + 1] = RotatePoint(vertices[(i * 4) + 1], center);
                        vertices[(i * 4) + 2] = RotatePoint(vertices[(i * 4) + 2], center);
                        vertices[(i * 4) + 3] = RotatePoint(vertices[(i * 4) + 3], center);
                    }

                    if (data.flippedHorizontally)
                    {
                        reversed = !reversed;
                        vertices[(i * 4) + 0].x = (center.x - vertices[(i * 4) + 0].x) + center.x;
                        vertices[(i * 4) + 1].x = (center.x - vertices[(i * 4) + 1].x) + center.x;
                        vertices[(i * 4) + 2].x = (center.x - vertices[(i * 4) + 2].x) + center.x;
                        vertices[(i * 4) + 3].x = (center.x - vertices[(i * 4) + 3].x) + center.x;
                    }

                    if (data.flippedVertically)
                    {
                        reversed = !reversed;
                        vertices[(i * 4) + 0].y = (center.y - vertices[(i * 4) + 0].y) + center.y;
                        vertices[(i * 4) + 1].y = (center.y - vertices[(i * 4) + 1].y) + center.y;
                        vertices[(i * 4) + 2].y = (center.y - vertices[(i * 4) + 2].y) + center.y;
                        vertices[(i * 4) + 3].y = (center.y - vertices[(i * 4) + 3].y) + center.y;
                    }
                }



                // Triangles
                if (!reversed)
                {
                    triangles[(i * 6) + 0] = (i * 4) + 0;
                    triangles[(i * 6) + 1] = (i * 4) + 1;
                    triangles[(i * 6) + 2] = (i * 4) + 2;
                    triangles[(i * 6) + 3] = (i * 4) + 1;
                    triangles[(i * 6) + 4] = (i * 4) + 3;
                    triangles[(i * 6) + 5] = (i * 4) + 2;
                }
                else
                {
                    triangles[(i * 6) + 0] = (i * 4) + 2;
                    triangles[(i * 6) + 1] = (i * 4) + 1;
                    triangles[(i * 6) + 2] = (i * 4) + 0;
                    triangles[(i * 6) + 3] = (i * 4) + 2;
                    triangles[(i * 6) + 4] = (i * 4) + 3;
                    triangles[(i * 6) + 5] = (i * 4) + 1;
                }


                // UVS
                uv[(i * 4) + 0] = new Vector2(uvRect.x / (float)layer.material.mainTexture.width, uvRect.yMax / (float)layer.material.mainTexture.height);
                uv[(i * 4) + 1] = new Vector2(uvRect.xMax / (float)layer.material.mainTexture.width, uvRect.yMax / (float)layer.material.mainTexture.height);
                uv[(i * 4) + 2] = new Vector2(uvRect.x / (float)layer.material.mainTexture.width, uvRect.y / (float)layer.material.mainTexture.height);
                uv[(i * 4) + 3] = new Vector2(uvRect.xMax / (float)layer.material.mainTexture.width, uvRect.y / (float)layer.material.mainTexture.height);
            }

            m.vertices  = vertices;
            m.triangles = triangles;
            m.uv        = uv;

            m.RecalculateNormals();
        }
    }
Exemplo n.º 3
0
    public static void InstantiatePrefabs(TileLayer layer)
    {
        if (layer.tileset == null)
        {
            return;
        }
        if (layer.tileset.tiles == null)
        {
            return;
        }

        Transform t = layer.transform.FindChild("TileInstances");

        if (t != null)
        {
            DestroyImmediate(t.gameObject);
        }
        t = layer.transform.FindChild("BoxColliders");
        if (t != null)
        {
            DestroyImmediate(t.gameObject);
        }

        GameObject instances          = new GameObject("TileInstances");
        Transform  instancesTransform = instances.transform;

        instancesTransform.parent        = layer.transform;
        instancesTransform.localPosition = new Vector3(0, 0, 0);
        instancesTransform.localScale    = new Vector3(1, 1, 1);
        instancesTransform.localRotation = new Quaternion(0, 0, 0, 0);

        GameObject boxes          = new GameObject("BoxColliders");
        Transform  boxesTransform = boxes.transform;

        boxesTransform.parent        = layer.transform;
        boxesTransform.localPosition = new Vector3(0, 0, 0);
        boxesTransform.localScale    = new Vector3(1, 1, 1);
        boxesTransform.localRotation = new Quaternion(0, 0, 0, 0);

        GameObject    prefab;
        GameObject    instance;
        GameObject    box;
        BoxCollider2D collider;
        Hashtable     skip = new Hashtable();

        if (layer.tileSpacing == new Vector2(-1, -1) || layer.tileSpacing == new Vector2(0, 0))
        {
            layer.tileSpacing = layer.tileSize;
        }

        for (int i = 0; i < layer.layerSize.x; i++)
        {
            for (int j = 0; j < layer.layerSize.y; j++)
            {
                UniTileTile tile = layer.GetTile(i, j);
                if (tile != null)
                {
                    TileInstance inst = layer.GetTileData(i, j);
                    prefab = tile.prefab;
                    if (prefab != null)
                    {
#if (UNITY_3_5 || UNITY_3_6 || UNITY_3_7 || UNITY_3_8 || UNITY_3_9)
                        instance = (GameObject)PrefabUtility.InstantiatePrefab(prefab);
#else
                        instance = (GameObject)PrefabUtility.InstantiatePrefab(prefab);
#endif
                        Vector3 scale = instance.transform.localScale;
                        instance.transform.parent     = instancesTransform;
                        instance.transform.localScale = scale;
                        Quaternion q = new Quaternion(0, 0, 0, 0);
                        q.eulerAngles = new Vector3(0, 0, (int)inst.rotation * 90);
                        instance.transform.localRotation = q;
                        instance.transform.localPosition = (Vector3)TileLayerUtil.TransformPoint(new Vector2(i * layer.tileSpacing.x + tile.prefabOffset.x, j * layer.tileSpacing.y + tile.prefabOffset.y), new Vector2(i * layer.tileSpacing.x + layer.tileSpacing.x / 2f, j * layer.tileSpacing.y +  +layer.tileSpacing.y / 2f), inst.flippedHorizontally, inst.flippedVertically, inst.rotation);
                        if (inst.flippedHorizontally)
                        {
                            instance.transform.localScale = new Vector3(-instance.transform.localScale.x, instance.transform.localScale.y, instance.transform.localScale.z);
                        }
                        if (inst.flippedVertically)
                        {
                            instance.transform.localScale = new Vector3(instance.transform.localScale.x, -instance.transform.localScale.y, instance.transform.localScale.z);
                        }
                    }
                    if (layer.collidable && tile.boxCollider)
                    {
                        if (skip[new Vector2(i, j)] == null)
                        {
                            if (tile.boxPrefab != null)
#if (UNITY_3_5 || UNITY_3_6 || UNITY_3_7 || UNITY_3_8 || UNITY_3_9)
                            { box = (GameObject)PrefabUtility.InstantiatePrefab(tile.boxPrefab); }
#else
                            { box = (GameObject)PrefabUtility.InstantiatePrefab(tile.boxPrefab); }
#endif
                            else
                            {
                                box = new GameObject("BoxCollider");
                            }

                            box.layer = tile.boxLayer;
                            box.tag   = tile.boxTag;
                            collider  = box.GetComponent <BoxCollider2D>();
                            if (!collider)
                            {
                                collider = box.AddComponent <BoxCollider2D>();
                            }
                            collider.sharedMaterial     = tile.boxMaterial;
                            box.transform.parent        = boxesTransform;
                            box.transform.localScale    = new Vector3(1, 1, 1);
                            box.transform.localRotation = new Quaternion(0, 0, 0, 0);
                            box.transform.localPosition = new Vector3(i * layer.tileSpacing.x, j * layer.tileSpacing.y, 0);

                            int sizeX = 1;
                            int sizeY = 1;
                            while (skip[new Vector2(i, j + sizeY)] == null && layer.CanMergeBoxColliders(i, j, i, j + sizeY))
                            {
                                skip[new Vector2(i, j + sizeY)] = true;
                                sizeY++;
                            }

                            if (sizeY == 1)
                            {
                                while (skip[new Vector2(i + sizeX, j)] == null && layer.CanMergeBoxColliders(i, j, i + sizeX, j))
                                {
                                    skip[new Vector2(i + sizeX, j)] = true;
                                    sizeX++;
                                }
                            }
                            else
                            {
                                sizeX = 1;
                                bool columnOk = true;
                                int  column   = 1;
                                while (columnOk)
                                {
                                    columnOk = true;
                                    for (int k = 0; k < sizeY; k++)
                                    {
                                        if (skip[new Vector2(i + column, j + k)] != null || !layer.CanMergeBoxColliders(i, j, i + column, j + k))
                                        {
                                            columnOk = false;
                                            break;
                                        }
                                    }
                                    if (columnOk)
                                    {
                                        column++;
                                    }
                                }
                                sizeX = column;
                                for (int k = 0; k < sizeX; k++)
                                {
                                    for (int l = 0; l < sizeY; l++)
                                    {
                                        skip[new Vector2(i + k, j + l)] = true;
                                    }
                                }
                            }

                            if (tile.customBoxDimensions)
                            {
                                Rect  rect = TileLayerUtil.TransformRect(tile.boxDimensions, layer.tileSize / 2f, inst.flippedHorizontally, inst.flippedVertically, inst.rotation);
                                float x    = rect.width;
                                float y    = rect.height;
                                if (rect.x == 0 && rect.xMax == layer.tileSpacing.x)
                                {
                                    x = layer.tileSpacing.x * sizeX;
                                }
                                if (rect.y == 0 && rect.yMax == layer.tileSpacing.y)
                                {
                                    y = layer.tileSpacing.y * sizeY;
                                }
                                collider.size   = new Vector3(x, y, tile.boxDepth);
                                collider.offset = new Vector3(collider.size.x / 2f + rect.x, collider.size.y / 2f + rect.y);
                            }
                            else
                            {
                                collider.size   = new Vector3(layer.tileSpacing.x * sizeX, layer.tileSpacing.y * sizeY, tile.boxDepth);
                                collider.offset = new Vector3(collider.size.x / 2f, collider.size.y / 2f);
                                //collider.center = new Vector3(layer.tileSpacing.x * sizeX / 2f, layer.tileSpacing.y * sizeY / 2f);
                            }
                        }
                    }
                }
            }
        }