Odpowiedzi:
Aby uzyskać tablicę ze wszystkimi kafelkami z prostokątnego obszaru mapy tilem, użyj tilemap.GetTilesBlock(BoundsInt bounds)
. Otrzymasz jednowymiarowy zestaw płytek, więc musisz wiedzieć sam, kiedy rozpocznie się następny rząd płytek. Wszelkie puste komórki będą reprezentowane przez null
wartość.
Jeśli chcesz wszystkie kafelki, użyj tilemap.cellBounds
. W ten sposób otrzymujesz BoundsInt
obiekt, który pokrywa cały wykorzystany obszar mapy tilem. Oto przykładowy skrypt, który pobiera wszystkie kafelki z Tilemapy na tym samym obiekcie gry i wyświetla kafelki z ich współrzędnymi:
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)");
}
}
}
}
}
Jeśli chodzi o granice i dlaczego możesz uzyskać więcej płytek, niż się spodziewasz: koncepcyjnie, Tilemaps Unity mają nieograniczony rozmiar. cellBounds
Rosną tak potrzebne podczas malowania płytek, ale nie kurczą się ponownie, jeśli je wymazać. Kiedy więc twoja gra ma dobrze zdefiniowany rozmiar mapy, możesz mieć pewne niespodzianki, jeśli poślizgniesz się podczas edytowania map. Istnieją trzy sposoby obejścia tego problemu:
tilemap.CompressBounds()
aby przywrócić granice skrajnych płytek (mając nadzieję, że pamiętasz, aby je usunąć)bounds
obiekt sam, new BoundsInt(origin, size)
zamiast na nim polegać cellBounds
.tilemap.origin
i tilemap.size
do żądanych wartości i następnie wywołanie tilemap.ResizeBounds()
.Oto inny sposób, aby to zrobić .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);
}
Podczas zastanawiania się, jak uzyskać wszystkie niestandardowe kafelki z Tilemap i ze względu na ITilemap
brak GetTilesBlock
metody, o której wspomniano w odpowiedziach, sugeruję dodanie metody rozszerzenia takiej (tylko 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();
}
}
W takim przypadku, jeśli masz, przypuszczalnie, niestandardowy kafelek TileRoad, odziedziczony z Tile lub TileBase, możesz uzyskać wszystkie kafelki TileRoad z wywołaniem:
TileBase[] = tilemap.GetTiles<RoadTile>();
W przypadku ITilemap możemy zmienić parametr (this Tilemap tilemap)
na, (this ITilemap tilemap)
ale tego nie sprawdziłem.
GetComponent<Tilemap>()
.