11
\$\begingroup\$

I have been trying a little bit the new TileMap system in Unity and I was looking for a way to access the tiles as a List or 2D array but I can't find anything other than GetTile(Vector3Int vector) which returns only one tile ... Is there any way to do this ?

\$\endgroup\$
15
\$\begingroup\$

To get an array with all tiles from a rectangular area of your tilemap, use tilemap.GetTilesBlock(BoundsInt bounds). You will get a one-dimensional array of tiles, so you need to know by yourself when the next row of tiles starts. Any empty cells will be represented with a null value.

If you want all tiles, use tilemap.cellBounds. This gets you a BoundsInt object which covers the complete used area of the tilemap. Here is an example script which gets all tiles from the Tilemap on the same game object and lists the tiles with their coordinates:

using UnityEngine;
using UnityEngine.Tilemaps;

public class TileTest : MonoBehaviour {
    void Start () {
        Tilemap tilemap = GetComponent<Tilemap>();

        BoundsInt bounds = tilemap.cellBounds;
        TileBase[] allTiles = tilemap.GetTilesBlock(bounds);

        for (int x = 0; x < bounds.size.x; x++) {
            for (int y = 0; y < bounds.size.y; y++) {
                TileBase tile = allTiles[x + y * bounds.size.x];
                if (tile != null) {
                    Debug.Log("x:" + x + " y:" + y + " tile:" + tile.name);
                } else {
                    Debug.Log("x:" + x + " y:" + y + " tile: (null)");
                }
            }
        }        
    }   
}

Regarding the bounds and why you might get more tiles than you expect: Conceptually, Unity Tilemaps have an unlimited size. The cellBounds grow as needed when you paint tiles, but they don't shrink again if you erase them. So when your game has a well-defined map size, you might get some surprises if you ever slip while editing maps. There are three ways to work around this issue:

\$\endgroup\$
11
\$\begingroup\$

Here is another way to do it with .cellBounds.allPositionsWithin

public Tilemap tilemap;
public List<Vector3> tileWorldLocations;

// Use this for initialization
void Start () {
    tileWorldLocations = new List<Vector3>();

    foreach (var pos in tilemap.cellBounds.allPositionsWithin)
    {   
        Vector3Int localPlace = new Vector3Int(pos.x, pos.y, pos.z);
        Vector3 place = tilemap.CellToWorld(localPlace);
        if (tilemap.HasTile(localPlace))
        {
            tileWorldLocations.Add(place);
        }
    }

    print(tileWorldLocations);
}
\$\endgroup\$
2
\$\begingroup\$

During figuring out how to get all custom tiles from Tilemap and due to ITilemap hasn't GetTilesBlock method which mentioned in answers I suggest to add an extension method like this (2D only):

public static class TilemapExtensions
{
    public static T[] GetTiles<T>(this Tilemap tilemap) where T : TileBase
    {
        List<T> tiles = new List<T>();

        for (int y = tilemap.origin.y; y < (tilemap.origin.y + tilemap.size.y); y++)
        {
            for (int x = tilemap.origin.x; x < (tilemap.origin.x + tilemap.size.x); x++)
            {
                T tile = tilemap.GetTile<T>(new Vector3Int(x, y, 0));
                if (tile != null)
                {
                    tiles.Add(tile);
                }
            }
        }
        return tiles.ToArray();
    }
}

In this case if you have, suppose, custom tile TileRoad, inherited from Tile or TileBase, then you can get all TileRoad tiles with call:

TileBase[] = tilemap.GetTiles<RoadTile>();

For ITilemap we can change parameter (this Tilemap tilemap) to (this ITilemap tilemap) but I didn't check that.

\$\endgroup\$
  • \$\begingroup\$ In what situation do you need to deal with the ITilemap interface? I didn't encounter it at all during my experiments with the Tilemap system. I always acquired the Tilemap component with GetComponent<Tilemap>(). \$\endgroup\$ – Philipp Dec 1 '17 at 14:21
  • \$\begingroup\$ ~Philipp, can't tell anything about interface, because I worked with Component only too. \$\endgroup\$ – Dmitry Tabakov Dec 19 '17 at 9:33

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.