Tilemapからすべてのタイルを取得する方法は?


13

TileMapUnity の新しいシステムを少し試しましたが、リストまたは2D配列としてタイルにアクセスする方法を探していましたが、GetTile(Vector3Int vector)1つのタイルのみを返すもの以外は見つかりません...方法はありますか?これをする ?

回答:


18

タイルマップの長方形の領域からすべてのタイルの配列を取得するには、を使用しますtilemap.GetTilesBlock(BoundsInt bounds)。タイルの1次元配列を取得するので、タイルの次の行がいつ始まるかを自分で知る必要があります。空のセルは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)");
                }
            }
        }        
    }   
}

境界と、予想よりも多くのタイルが得られる理由について:概念的には、Unityタイルマップのサイズは無制限です。cellBoundsあなたはタイルをペイントする際、必要に応じて成長していますが、それらを消去した場合、彼らは再び収縮しません。そのため、ゲームのマップサイズが明確に定義されている場合、マップの編集中にずれると、驚くことがあります。この問題を回避するには3つの方法があります。

  • 呼び出しtilemap.CompressBounds()て、境界を最も外側のタイルに復元します(タイルを消去することを忘れないでください)
  • に依存boundsするnew BoundsInt(origin, size)代わりに、自分でオブジェクトを作成しますcellBounds
  • を目的の値に設定tilemap.originしてtilemap.sizeから、を呼び出しますtilemap.ResizeBounds()

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から継承されたカスタムタイルTileRoadがあるとすると、次の呼び出しですべてのTileRoadタイルを取得できます。

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

ITilemapの場合、パラメーターをに変更できます(this Tilemap tilemap)(this ITilemap tilemap)、チェックしませんでした。


どのような状況でITilemapインターフェイスを処理する必要がありますか?Tilemapシステムを使った実験中にはまったく遭遇しませんでした。私は常にTilemapコンポーネントをで取得しましたGetComponent<Tilemap>()
Philipp

〜フィリップ、インターフェースについては何も言えません。私もコンポーネントでしか作業していないからです。
Dmitry Tabakov
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.