Como obter todos os blocos de um Tilemap?

13

Eu tenho tentado um pouco o novo TileMapsistema no Unity e estava procurando uma maneira de acessar os blocos como uma lista ou matriz 2D, mas não consigo encontrar outra coisa senão GetTile(Vector3Int vector)que retorne apenas um bloco ... Existe alguma maneira para fazer isso ?

Shashimee
fonte

Respostas:

18

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 nullvalor.

Se você quiser todas as peças, use tilemap.cellBounds. Isso BoundsIntgera 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 cellBoundscrescer 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:

Philipp
fonte
11

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);
}
codificado
fonte
2

Durante a descoberta de como obter todos os blocos personalizados do Tilemap e, devido ao método ITilemapnão GetTilesBlockmencionado 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.

Dmitry Tabakov
fonte
Em que situação você precisa lidar com a interface do ITilemap? Não encontrei nada durante minhas experiências com o sistema Tilemap. Eu sempre adquiri o componente Tilemap GetComponent<Tilemap>().
Philipp
~ Philipp, não posso contar nada sobre interface, porque também trabalhei com o Component.
Dmitry Tabakov