如何从Tilemap获取所有图块?


13

我一直在尝试TileMap在Unity中使用新系统,我一直在寻找一种以列表或2D数组形式访问图块的方法,但是除了GetTile(Vector3Int vector)返回仅一个图块之外,我什么都找不到。去做这个 ?

Answers:


18

要从图块贴图的矩形区域获取包含所有图块的数组,请使用tilemap.GetTilesBlock(BoundsInt bounds)。您将获得一维拼贴块,因此您需要自己知道下一排拼贴块何时开始。任何空单元格都将用一个null值表示。

如果需要所有图块,请使用tilemap.cellBounds。这将为您提供一个BoundsInt覆盖tilemap完整使用区域的对象。这是一个示例脚本,该脚本从同一个游戏对象上的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)");
                }
            }
        }        
    }   
}

关于边界以及为什么您可以获得比预期更多的图块:从概念上讲,Unity Tilemap具有无限大小。在cellBounds需要的时候你画砖,但如果你删除他们,他们不要再缩水增长。因此,当您的游戏具有明确定义的地图尺寸时,如果您在编辑地图时滑倒,可能会有些意外。有三种方法可以解决此问题:


11

这是另一种方法 .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);
}

2

在弄清楚如何从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();
    }
}

在这种情况下,假设您拥有自Tile或TileBase继承的自定义tile TileRoad,则可以通过调用获取所有TileRoad tile:

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

对于ITilemap,我们可以将参数更改(this Tilemap tilemap)为,(this ITilemap tilemap)但是我没有检查。


在什么情况下需要处理ITilemap界面?在使用Tilemap系统进行实验的过程中,我根本没有遇到过。我总是使用来获得Tilemap组件GetComponent<Tilemap>()
菲利普

〜Philipp,关于接口什么也不能说,因为我也只使用Component。
德米特里·塔巴科夫
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.