見出し画像

【Unity2D】タイルマップの水面に橋をかけて通行可能にする

私はUnityのタイルマップに通行不能な水面を配置し、その上に橋などをかけて通行可能にしたいと思ったことがあります。RPGなどでよくあるものですが、それについて調べてみてもなかなか有用な情報は得られませんでした。
でも自分でいい方法を見つけることができたので書き記しておきます。

※タイルマップについてある程度理解できている方向けの内容です。


筆者の環境

  • Unity 2021.3.21f1

  • 2D URP

方法

1. タイルマップを3枚(地面、水面、橋などの物体)作成

左のヒエラルキーのようにタイルマップを3枚作成

各タイルマップの重なり順(Order in Layer)を

  • Ground(地面): 0

  • Water(水面): 1

  • Objects(橋などの物体): 2

に設定し、地面や水面、橋などのタイルを適切なタイルマップに配置していきます。

タイルの素材・アセットは以下のサイトから使用しました(キャラクターは自作です)。
いずれも(執筆時点では)無料です。おすすめです。

2. 水面の当たり判定を追加

水面のタイル当たり判定(Collider Type)をGridに設定します。

水面のタイルマップにTilemap Collider 2Dをアタッチします。

これで、(あらかじめRigidbody 2DとCircle Collider 2Dの付いた)キャラクターと水面の衝突判定が行われるようになります。

3. 以下のスクリプト(Bridge)を作成

using UnityEngine;
using UnityEngine.Tilemaps;

/// <summary>水面に橋をかけて通行可能にする。タイルマップの親にアタッチ</summary>
public class Bridge : MonoBehaviour
{
    [SerializeField] Tilemap waterMap;//水面のタイルマップ。TilemapCollider2D必須
    [SerializeField] Tilemap objectsMap;//橋などがあるタイルマップ
    [SerializeField] TileBase[] bridgeTiles;//橋(通行可能)タイル

    // Start is called before the first frame update
    void Start()
    {
        waterMap.GetComponent<TilemapCollider2D>().enabled = false;//表示用のタイルマップの衝突判定はOFF
        Tilemap waterMap2 = Instantiate(waterMap, transform);//当たり判定専用のタイルマップを追加

        foreach (Vector3Int pos in objectsMap.cellBounds.allPositionsWithin)//橋などがあるタイルマップの全マスを調査
        {
            Vector3Int cellPosition = new Vector3Int(pos.x, pos.y, pos.z);

            if (waterMap2.HasTile(cellPosition))//当たり判定専用のタイルマップの該当位置に水面(当たり判定あり)のタイルがあれば
            {
                foreach (TileBase tile in bridgeTiles)
                {
                    if (objectsMap.GetTile(cellPosition) == tile)//橋があれば
                    {
                        waterMap2.SetTile(cellPosition, null);//当たり判定専用のタイルマップから水面タイルを消去
                        break;
                    }
                }
            }
        }

        waterMap2.GetComponent<TilemapCollider2D>().enabled = true;//当たり判定専用のタイルマップの当たり判定ON
        waterMap2.GetComponent<TilemapRenderer>().enabled = false;//当たり判定専用のタイルマップを非表示にする
    }
}

4. BridgeスクリプトをGridにアタッチ

先ほど作成したBridgeスクリプトをタイルマップの親(Grid)にアタッチします。

Water Mapには水面のタイルマップを、Objects Mapにはなどの物体のタイルマップを設定します。

Bridge Tilesには橋として通行可能にしたいタイル(複数可)を設定します。

このように設定
完成イメージ(キャラクターコントローラーはここでは解説しません)

最後に

上記の方法で、RPG制作でよくある橋の通行設定を実装できました。
ウディタ(私は触ったことがない)などでは簡単に実装できるようですが、Unityでやるには一工夫が必要です。
内部的には表示用のタイルマップと当たり判定専用のタイルマップを分けているだけですが、手動で設定するのは手間でミスも多いので、自動化するようにしました。
このシステムはほぼそのままの形で、崖をはしごや階段などで登れるようにすることにも応用できそうですね。

この記事が気に入ったらサポートをしてみませんか?