Comment obtenir toutes les tuiles d'un Tilemap?

13

J'ai essayé un peu le nouveau TileMapsystème dans Unity et je cherchais un moyen d'accéder aux tuiles en tant que liste ou tableau 2D mais je ne trouve rien d'autre que celui GetTile(Vector3Int vector)qui ne renvoie qu'une seule tuile ... Y a-t-il un moyen pour faire ça ?

Shashimee
la source

Réponses:

18

Pour obtenir un tableau avec toutes les tuiles d'une zone rectangulaire de votre tilemap, utilisez tilemap.GetTilesBlock(BoundsInt bounds). Vous obtiendrez un tableau unidimensionnel de tuiles, vous devez donc savoir par vous-même quand la prochaine rangée de tuiles commence. Toutes les cellules vides seront représentées avec une nullvaleur.

Si vous voulez toutes les tuiles, utilisez tilemap.cellBounds. Cela vous donne un BoundsIntobjet qui couvre toute la zone utilisée du tilemap. Voici un exemple de script qui récupère toutes les tuiles du Tilemap sur le même objet de jeu et répertorie les tuiles avec leurs coordonnées:

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)");
                }
            }
        }        
    }   
}

En ce qui concerne les limites et pourquoi vous pourriez obtenir plus de tuiles que vous attendez: Conceptuellement, les Tilemaps Unity ont une taille illimitée. Ils cellBoundspoussent au besoin lorsque vous peignez des carreaux, mais ils ne rétrécissent plus si vous les effacez. Ainsi, lorsque votre jeu a une taille de carte bien définie, vous pourriez obtenir des surprises si vous vous glissez lors de la modification des cartes. Il existe trois façons de contourner ce problème:

Philipp
la source
11

Voici une autre façon de le faire avec .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);
}
allencoded
la source
2

Lors de la détermination de la façon d'obtenir toutes les tuiles personnalisées de Tilemap et en raison de la méthode ITilemapnon GetTilesBlockmentionnée dans les réponses, je suggère d'ajouter une méthode d'extension comme celle-ci (2D uniquement):

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();
    }
}

Dans ce cas, si vous avez, supposons, des tuiles personnalisées TileRoad, héritées de Tile ou TileBase, vous pouvez obtenir toutes les tuiles TileRoad avec appel:

TileBase[] = tilemap.GetTiles<RoadTile>();

Pour ITilemap, nous pouvons changer le paramètre (this Tilemap tilemap)en (this ITilemap tilemap)mais je n'ai pas vérifié cela.

Dmitry Tabakov
la source
Dans quelle situation avez-vous besoin de gérer l'interface ITilemap? Je ne l'ai pas rencontré du tout lors de mes expériences avec le système Tilemap. J'ai toujours acquis le composant Tilemap avec GetComponent<Tilemap>().
Philipp
~ Philipp, je ne peux rien dire sur l'interface, car je n'ai travaillé qu'avec Component aussi.
Dmitry Tabakov