Respostas:
Para obter uma matriz com todos os blocos de uma área retangular do seu mapa de blocos, use tilemap.GetTilesBlock(BoundsInt bounds)
. Você obterá uma matriz unidimensional de blocos, portanto precisará saber quando a próxima linha de blocos iniciar. Quaisquer células vazias serão representadas com um null
valor.
Se você quiser todas as peças, use tilemap.cellBounds
. Isso BoundsInt
gera um objeto que cobre toda a área usada do mapa de peças. Aqui está um exemplo de script que obtém todos os blocos do Tilemap no mesmo objeto de jogo e lista os blocos com suas coordenadas:
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)");
}
}
}
}
}
Em relação aos limites e por que você pode obter mais peças do que o esperado: conceitualmente, os Unity Tilemaps têm um tamanho ilimitado. A cellBounds
crescer conforme necessário, quando você pintar azulejos, mas eles não encolher novamente, se você apagá-las. Portanto, quando o seu jogo tiver um tamanho de mapa bem definido, você poderá ter algumas surpresas se escorregar durante a edição de mapas. Existem três maneiras de solucionar esse problema:
tilemap.CompressBounds()
para restaurar os limites para os blocos mais extremos (esperando que você se lembre de apagá-los)bounds
objeto com você em new BoundsInt(origin, size)
vez de confiar cellBounds
.tilemap.origin
e tilemap.size
com os valores desejados e depois chame tilemap.ResizeBounds()
.Aqui está outra maneira de fazer isso com .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);
}
Durante a descoberta de como obter todos os blocos personalizados do Tilemap e, devido ao método ITilemap
não GetTilesBlock
mencionado nas respostas, sugiro adicionar um método de extensão como este (somente 2D):
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();
}
}
Nesse caso, se você tiver, suponha, o tileRoad personalizado, herdado de Tile ou TileBase, poderá obter todos os tiles de TileRoad com a chamada:
TileBase[] = tilemap.GetTiles<RoadTile>();
Para o ITilemap , podemos alterar o parâmetro (this Tilemap tilemap)
para, (this ITilemap tilemap)
mas não verifiquei isso.
GetComponent<Tilemap>()
.