Відповіді:
Щоб отримати масив із усіма плитками з прямокутної області вашої карти плиток, використовуйте tilemap.GetTilesBlock(BoundsInt bounds)
. У вас вийде одновимірний масив плиток, тому вам потрібно знати самі, коли починається наступний ряд плиток. Будь-які порожні комірки будуть представлені зі null
значенням.
Якщо ви хочете всю плитку, використовуйте tilemap.cellBounds
. Це дає вам BoundsInt
об'єкт, який охоплює всю використану область кавової карти. Ось приклад сценарію, який отримує всі плитки з Tilemap на одному ігровому об’єкті та перераховує плитки з їх координатами:
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)");
}
}
}
}
}
Що стосується меж та чому ви можете отримати більше плиток, ніж ви очікували: Концептуально Tilemaps Unity має необмежений розмір. cellBounds
Рости по мірі необхідності , коли ви малюєте плитки, але вони не дають усадку знову , якщо ви видалите їх. Тож, коли у вашій грі чітко визначений розмір карти, ви можете отримати сюрпризи, якщо ви коли-небудь сповзатимете під час редагування карт. Існує три способи вирішити цю проблему:
tilemap.CompressBounds()
щоб відновити межі до самих плиток (сподіваючись, що ви пам’ятаєте, що стерти їх)bounds
об’єкт самостійно, new BoundsInt(origin, size)
а не покладатися на нього cellBounds
.tilemap.origin
і tilemap.size
бажані значення, а потім зателефонуйте tilemap.ResizeBounds()
.Ось ще один спосіб зробити це .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);
}
Під час з'ясувати , як отримати всі призначені для користувача плитки з Tilemap і з - за ITilemap
не має GetTilesBlock
метод , який згадується у відповідях я пропоную , щоб додати метод розширення , як це (тільки 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();
}
}
У цьому випадку, якщо у вас, припустимо, власна плитка TileRoad, успадкована від Tile або TileBase, ви можете отримати всі плитки TileRoad з викликом:
TileBase[] = tilemap.GetTiles<RoadTile>();
Для ITilemap ми можемо змінити параметр , (this Tilemap tilemap)
щоб (this ITilemap tilemap)
але я не перевіряв це.
GetComponent<Tilemap>()
.