Tilemapの情報をスクリプト上から取得して特定のtileの場合何か処理をしたい

Unity

タイトルの通りなのですが

Tilemapで何かしらのタイルの場合のみ

なんか処理を行いたいってなんとなく思いました。

ちなみにTilemapって何?という方はよければまずは以下を見てみてください!



なんかやりたいことがザックリしまくっていますが

なんとなく調べた内容をなんとなくこちらに記載していこうかなーなんて

思っていたりいなかったりしています。

ではいきましょー!

とりあえず以下のようなことを実装してみました。

ボタンを押したら特定のタイルのスプライトが変更されていますね。

自分で描写したTilemapの情報をスクリプト上で取得したい!

これどうするん?って思ったのですが

以下にやり方が記載されていました。

Attention Required! | Cloudflare

てかぶっちゃけこの上記のやり方を真似すれば情報を取得できます。


なので以下では自分が疑問に思ったところを

ちょっと詳しく記載していこうと思います。


まずはtilemapの全体像を取得する方法です。
こちらは以下で取得できます。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Tilemaps;

public class TilemapController : MonoBehaviour
{
    public Tilemap tilemap;
    public Sprite sprite;

    public void replaceTilemap()
    {
        foreach (var pos  in tilemap.cellBounds.allPositionsWithin)
        {
            // 何かの処理
        }
    }
}

tilemap.cellBounds.allPositionsWithin
という訳の分からないことをしていますね。


まず英語の意味をとらえましょう。

「cellBounds」の「Bounds」という言葉ですが

日本語訳すると「境界」という意味になります。


で次に「allPositionsWithin」は「以内の全ての位置」と訳せるので

合せると「境界内の全ての位置情報」です。


ってことで

tilemap.cellBounds.allPositionsWithin

とすることによってタイルマップの境界内の全ての位置情報を取得しているんです。

Unity - Scripting API: Tilemaps.Tilemap.cellBounds

でここでの疑問は「境界」ってどこのこと言っているの?ですよね。

これはつまり座標の最大値、最小値です。


該当のタイルマップ内で一番端に描かれたセルの座標情報って

どうなっている?っていうことを取得できます。


つまり一番右端・左端に描かれたセルの座標情報や

一番上端・下端に描かれたセルの座標情報が取得できるということです。

Tilemap.cellBoundsがそういった端の情報を取得する処理です。

BoundsInt bounds = Tilemap.cellBounds;

とすると境界の情報が取得できます。


例えば最大のx座標を取得したい場合

bounds.max.x

で取得できます。

他にも以下のようにすれば

それぞれのx,y座標が取得できるわけです。

bounds.max.x
bounds.min.x
bounds.max.y
bounds.min.y

以下のTilemapの描写であれば以下の座標を取得しています。


ということでなんとなく境界がどこのことを指しているか
理解できたでしょうか。

その上で「allPositionsWithin」で境界内に含まれた全ての位置情報を
取得できます。

特定のtileの場合何か処理をしたい

とりあえず全てのタイルマップ情報が取得できるということが分かったので
ループで回していけば描画された全てのタイルマップの状態を取得できます。

あとはその中で特定のタイルの場合何か処理を行います。

例えば今回は冒頭で説明した通り特定のスプライトの場合、そのスプライトを変更してみましょう。

それを表現したのが以下になります。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Tilemaps;

public class TilemapController : MonoBehaviour
{
    public Tilemap tilemap;
    public TileBase replaceTile;
    public Sprite sprite;

    public void replaceTilemap()
    {
        foreach (var pos in tilemap.cellBounds.allPositionsWithin)
        {
            // 取り出した位置情報からタイルマップ用の位置情報(セル座標)を取得
            Vector3Int cellPosition = new Vector3Int(pos.x, pos.y, pos.z);
   
            // tilemap.HasTile -> タイルが設定(描画)されている座標であるか判定
            if (tilemap.HasTile(cellPosition))
            {
                // スプライトが一致しているか判定
                if (tilemap.GetSprite(cellPosition) == sprite)
                {
                    // 特定のスプライトと一致している場合は別のタイルを設定する
                    tilemap.SetTile(cellPosition, replaceTile);
                }
            }
        }
    }
}

今回はこのスクリプト名をTilemapControllerとしました。

で、Hierarchyウィンドウ上で
右クリック→Create Empty
で空のゲームオブジェクトを作成します。

そこに上記で作成したスクリプトをアタッチします。

で変数のtilemap、replaceTile、spriteを設定します。
TilemapControllerオブジェクトのInspectorウィンドウは以下のような感じです。

最後に新たにボタンを追加し
Onclick時に呼び出される関数をreplaceTilemapにしてあげます。

ではゲーム実行してボタンを押してみましょう!

なんともあっさりした処理ですが
ボタンを押した瞬間にグレーのタイルが置き換わりましたね!

おわりに

いかがでしたでしょうか。

分かれば案外簡単ですが分からないと
タイルマップの情報をスクリプト上で取得するのは
難しそうに感じますよね。

でもやってみるとそこまで難しくないかなって話でした!

タイトルとURLをコピーしました