Jak zdobyć wszystkie płytki z Tilemap?

13

Próbowałem trochę nowego TileMapsystemu w Unity i szukałem sposobu, aby uzyskać dostęp do kafelków jako tablicy lub tablicy 2D, ale nie mogę znaleźć niczego innego, GetTile(Vector3Int vector)co zwraca tylko jeden kafelek ... Czy jest jakiś sposób zrobić to?

Shashimee
źródło

Odpowiedzi:

18

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 nullwartość.

Jeśli chcesz wszystkie kafelki, użyj tilemap.cellBounds. W ten sposób otrzymujesz BoundsIntobiekt, 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. cellBoundsRosną 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:

Philipp
źródło
11

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);
}
zakodowany
źródło
2

Podczas zastanawiania się, jak uzyskać wszystkie niestandardowe kafelki z Tilemap i ze względu na ITilemapbrak GetTilesBlockmetody, 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.

Dmitrij Tabakov
źródło
W jakiej sytuacji musisz poradzić sobie z interfejsem ITilemap? Nie spotkałem go wcale podczas eksperymentów z systemem Tilemap. Zawsze kupowałem komponent Tilemap GetComponent<Tilemap>().
Filipiny
~ Philipp, nie mogę nic powiedzieć o interfejsie, ponieważ pracowałem tylko z Component.
Dmitrij Tabakov,