2019-03-04に投稿

Tilemapからミニマップを作成してみた②

読了目安:10分

前回の続きです。
Tilemapからミニマップを作成してみた①

(今はこんな感じ)
image.png

テクスチャサイズを調整する(余白を作る)

上記の画像を見ると、カメラのサイズに対してマップのサイズが小さく見えます。
これは背景(透明黒色の部分)が十分な大きさで作成されていないからです。
なので、テクスチャのサイズを少し大きくします。

1.MinMap.csを以下のように変更します。

public class MiniMap : MonoBehaviour
{
    [SerializeField] Transform _grid;
    [SerializeField] Image _image;

    // マップの色
    [SerializeField] Color _wallColor;
    [SerializeField] Color _groundColor;
    [SerializeField] Color _noneColor;

    // 余白
    [SerializeField] int _space = 20;

    // マップ用テクスチャ
    Texture2D _texture;



    void Start()
    {
        Tilemap groundTilemap = _grid.Find("Ground").GetComponent<Tilemap>();
        Tilemap wallTilemap = _grid.Find("Wall").GetComponent<Tilemap>();

        // テクスチャ作成
        Vector3Int size = new Vector3Int(wallTilemap.size.x + _space * 2, wallTilemap.size.y + _space * 2, wallTilemap.size.z);
        _texture = new Texture2D(size.x, size.y, TextureFormat.ARGB32, false);

        // こうしないと、画像がぼやける
        _texture.filterMode = FilterMode.Point;

        Vector3Int origin = new Vector3Int(wallTilemap.origin.x - _space, wallTilemap.origin.y - _space, wallTilemap.origin.z);

......

2.「MinMap」の「Space」をちょうどいい値に調整
image.png

サイズがちょうどいい感じになりました。
image.png

マップ背景を透明にする

今はマップの後ろが不透明なので、例えばここに敵がいた場合見つけることができず、プレイヤーにストレスを与えることになります。
なのでマップの後ろを見えるようにします。

1.「MiniMap」の「None Color」をちょうどいい透明度にする
image.png

2.「MiniMap>Camera」の「Clear Flags」を「Depth Only」に変更する
image.png

そうすると、こんな感じになります。
image.png

マップをプレイヤーに追従させる

現在はプレイヤーが動いてもマップは止まったままです。
blog.gif
これを、プレイヤーに合わせて描画内容が変わるようにします。

1.Standard Assetsをインポートする
Standard Assets

2.「MiniMap>Camera」に「FollowTarget」を追加し、設定を以下のように変更

  • 「Target」にプレイヤーオブジェクトを設定
  • 「Offset」をCameraの座標と同じにする
    image.png

こんな感じになりました。
blog.gif

マップにプレイヤーを表示する

1.プレイヤーオブジェクトの下に、マップ上で表示するSprite Rendererを作成し、設定を以下のように変更

  • 「Layer」を「MiniMap」に変更
  • 「Order in Layer」を「MiniMap>Canvas」よりも上にする

image.png

表示されました。
blog.gif

壁を細くする

今回のステージの壁は、3Grid使って表示しています。
ただこれをそのままマップ上で表示すると壁が太く見えるので、地面タイルに隣接している壁のみ表示するように変更します。
隣接しているか確認するのは、上下左右斜めの8方向です。

1.「MiniMap.cs」を以下のように変更

......

        // 地面タイルが存在するか確認する方向
        Vector3Int[] directions = new Vector3Int[]
        {
            new Vector3Int(-1, 0, 0), new Vector3Int(1, 0, 0), new Vector3Int(0, -1, 0), new Vector3Int(0, 1, 0),
            new Vector3Int(-1, -1, 0), new Vector3Int(1, -1, 0), new Vector3Int(1, 1, 0), new Vector3Int(-1, 1, 0),
        };

        // テクスチャ座標ごとの色を求める
        for (int y = 0; y < size.y; ++y)
        {
            for (int x = 0; x < size.x; ++x)
            {
                // Tilemapのグリッド座標
                Vector3Int cellPos = new Vector3Int(origin.x + x, origin.y + y, 0);

                // マップカラー
                Color color = _noneColor;

                // 壁タイルが存在する
                if (wallTilemap.GetTile(cellPos) != null)
                {
                    // 8方向のどこかに地面タイルが存在するかチェック
                    for (int i = 0; i < directions.Length; ++i)
                    {
                        if (groundTilemap.GetTile(cellPos + directions[i]) != null)
                        {
                            color = _wallColor;

                            break;
                        }
                    }  
                }
                // 地面タイルが存在する
                else if (groundTilemap.GetTile(cellPos) != null)
                {
                    color = _groundColor;
                }

                _texture.SetPixel(x, y, color);
            }
        }
......        

壁が細くなりました。
image.png

おわりに

一応、最終的なMiniMap.csを書いておきます。
次は、一度確認した箇所だけ表示されるマップや、フロア単位で表示されるマップを作ろうと思います。

using UnityEngine;
using UnityEngine.Tilemaps;
using UnityEngine.UI;

public class MiniMap : MonoBehaviour
{
    [SerializeField] Transform _grid;
    [SerializeField] Image _image;

    // マップの色
    [SerializeField] Color _wallColor;
    [SerializeField] Color _groundColor;
    [SerializeField] Color _noneColor;

    // 余白
    [SerializeField] int _space = 20;

    // マップ用テクスチャ
    Texture2D _texture;



    void Start()
    {
        Tilemap groundTilemap = _grid.Find("Ground").GetComponent<Tilemap>();
        Tilemap wallTilemap = _grid.Find("Wall").GetComponent<Tilemap>();

        // テクスチャ作成
        int width = wallTilemap.size.x + _space * 2;
        int height = wallTilemap.size.y + _space * 2;

        Vector3Int size = new Vector3Int(width, height, wallTilemap.size.z);
        _texture = new Texture2D(size.x, size.y, TextureFormat.ARGB32, false);

        // こうしないと、画像がぼやける
        _texture.filterMode = FilterMode.Point;

        Vector3Int origin = new Vector3Int(wallTilemap.origin.x - _space, wallTilemap.origin.y - _space, wallTilemap.origin.z);

        // 地面タイルが存在するか確認する方向
        Vector3Int[] directions = new Vector3Int[]
        {
            new Vector3Int(-1, 0, 0), new Vector3Int(1, 0, 0), new Vector3Int(0, -1, 0), new Vector3Int(0, 1, 0),
            new Vector3Int(-1, -1, 0), new Vector3Int(1, -1, 0), new Vector3Int(1, 1, 0), new Vector3Int(-1, 1, 0),
        };

        // テクスチャ座標ごとの色を求める
        for (int y = 0; y < size.y; ++y)
        {
            for (int x = 0; x < size.x; ++x)
            {
                // Tilemapのグリッド座標
                Vector3Int cellPos = new Vector3Int(origin.x + x, origin.y + y, 0);

                // マップカラー
                Color color = _noneColor;

                // 壁タイルが存在する
                if (wallTilemap.GetTile(cellPos) != null)
                {
                    // 8方向のどこかに地面タイルが存在するかチェック
                    for (int i = 0; i < directions.Length; ++i)
                    {
                        if (groundTilemap.GetTile(cellPos + directions[i]) != null)
                        {
                            color = _wallColor;

                            break;
                        }
                    }  
                }
                // 地面タイルが存在する
                else if (groundTilemap.GetTile(cellPos) != null)
                {
                    color = _groundColor;
                }

                _texture.SetPixel(x, y, color);
            }
        }

        // テクスチャ確定
        _texture.Apply();

        // テクスチャをImageに適用
        _image.rectTransform.sizeDelta = new Vector2(size.x, size.y);
        _image.sprite = Sprite.Create(_texture, new Rect(0, 0, size.x, size.y), Vector2.zero);

        // _imageをGridの中心に移動
        Vector2 leftDownWorldPos = wallTilemap.CellToWorld(origin);
        Vector2 rightUpWorldPos = wallTilemap.CellToWorld(origin + size);
        _image.transform.position = (leftDownWorldPos + rightUpWorldPos) * 0.5f;
    }

    private void OnDestroy()
    {
        Destroy(_texture);
    }
}

長野別荘

福岡の片隅で友人と何か作ってます。 Steamでマッチ3パズルゲーム「TAVERN GUARDIANS: BANQUET」配信中。

Crieitはβバージョンで開発中です。進捗は公式Twitterアカウントをフォローして確認してください。 興味がある方は是非記事の投稿もお願いします! どんな軽い内容でも嬉しいです。
なぜCrieitを作ろうと思ったか

また、「こんな記事が読みたいけど見つからない!」という方は是非記事投稿リクエストボードへ!

関連記事

コメント