I think a useful addition to the TileMap API would be ContainsTile. Here is the use case…
In my game, there are “themes” for each level. Each theme uses different sets of tiles. I like to be able to switch themes in the editor to see how a level would look with different themes. I use TileMap.SwapTile for this. However, if working in the editor, TileMap.SwapTile is potentially dangerous. If I accidentally swap to a tile that is already in the tile map, I could lose data.
Here’s some pseudo code:
void SwapThemes(Theme oldTheme, Theme newTheme) {
for (int i = 0; i < newTheme.tiles.Length; i++) {
var newTile = newTheme.tiles[i];
Assert.IsFalse(tileMap.Contains(newTile), "Tile map already contains tiles from that theme!");
tileMap.SwapTile(oldTheme.tiles[i], newTile);
}
}
I know I can do it with an extension method but it won’t be very performant since I will have to iterate through every cell. I thought another similar useful addition could be TileMap.uniqueTiles. It would return an IEnumerable of all the tiles currently used in the map.
Edit: Here are the extension methods I wrote.
public static IEnumerable<BaseTile> Tiles(this TileMap tileMap) {
var size = tileMap.size;
for (int y = 0; y < size.y; y++) {
for (int x = 0; x < size.x; x++) {
if (tileMap.GetTile(new Vector3Int(x, y, 0)))
yield return tileMap.GetTile(new Vector3Int(x, y, 0));
}
}
}
public static IEnumerable<BaseTile> UniqueTiles(this TileMap tileMap) {
return tileMap.Tiles().Distinct();
}
public static bool ContainsTile(this TileMap tileMap, BaseTile tile) {
return tileMap.UniqueTiles().Contains(tile);
}
public static void SwapTileSafely(this TileMap tileMap, BaseTile oldTile, BaseTile newTile) {
Assert.IsFalse(tileMap.ContainsTile(newTile), "Swap tile failed. Tile Map " + tileMap.name + " already contains " + newTile.name);
tileMap.SwapTile(oldTile, newTile);
}