Unity(C#)初心者・入門者向けチュートリアル ひよこのたまご

AndroidやiOS向けアプリを簡単に作れるゲーム開発環境Unity(ユニティ)の使い方を、チュートリアル方式で一緒に学びましょう!

【Unity】2Dタイルマップ17 2マスで1オブジェクトのTileを掴んで、移動させて、配置する

Unity 2021.1.0f1 Personal(2021年3月)
f:id:hiyotama:20210327033253p:plain

今回は以前投稿した【Unity】2Dタイルマップ12 Tileを掴んで、移動させて、配置するをアップデートします!

hiyotama.hatenablog.com

長テーブルなど2マスで1オブジェクトを表すTileを上記記事と同様に移動させていきます。

2マスで1オブジェクトのTileを準備する

今回は長テーブルのスプライトを用意しました。

f:id:hiyotama:20210327024542p:plain
table_f.png

f:id:hiyotama:20210327024547p:plain
table_r.png

過去記事を参考にTilePaletteへ登録します。(前回記事で使ったタンスも残しておきます。)

f:id:hiyotama:20210327024923p:plain

2マスで1オブジェクトのTile情報を保存できるScriptableObject

Tile情報を保存したScriptableObjectを過去記事で作成しました。

hiyotama.hatenablog.com

2マスで1オブジェクトのTile情報を保存できるようにアップデートしていきます。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
using UnityEngine.Tilemaps;
[CreateAssetMenu]
public class TileScriptableObject : ScriptableObject
{
    public List<TileStore> tileDataList = new List<TileStore>();
}
[Serializable]
public class TileStore
{
    public string name;
    public Tile[] tiles;
}

TileScriptableObject.cs

こちらのScriptableObjectを生成し、tansuとtableのTileを登録します。
ルールとしては奥にくるTileから順に登録します。(tableの場合はtable_f、table_rの順番)

f:id:hiyotama:20210327025618p:plain
ScriptableObjectにTileを登録

以上でScriptableObjectの準備は完了です。

Tilemapを作成する

続いてTilemapを作成します。
家具配置用のTilemap(FurnitureTIlemap)と移動用のTilemap(MoveTilemap)を作成します。
移動用のみposition.yを0.1にします。

f:id:hiyotama:20210327030205p:plain
MoveTilemapのposition.yを変更

Tileの移動をコントロールするScript作成

最後にTileの移動をコントロールするScript(MoveTileController.cs)を用意し、Controllerという名前のオブジェクト作成して取り付けます。

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


public class MoveTileController : MonoBehaviour
{
    [SerializeField] TileScriptableObject tileSO;
    [SerializeField] Tilemap defaultTilemap;
    [SerializeField] Tilemap moveTilemap;

    private Vector3Int selectPos;
    private PlacedTiles selectTile;
    private List<PlacedTiles> placedTiles = new List<PlacedTiles>();


    private void Start()
    {
        SetFurniture("tansu", 0, 0);
        SetFurniture("table", 2, 3);
    }


    private void SetFurniture(string name, int x, int y)
    {
        var tileStore = tileSO.tileDataList.Single(t => t.name == name);

        for (int i = 0; i < tileStore.tiles.Length; i++)
        {
            defaultTilemap.SetTile(new Vector3Int(x, y-i, 0), tileStore.tiles[i]);
        }

        placedTiles.Add(new PlacedTiles(tileStore, x, y));
    }


    private void Update()
    {
        if (Input.GetMouseButtonDown(0))
        {
            SelectTile();
        }
        else if (Input.GetMouseButton(0) && selectTile != null)
        {
            MoveTile();
        }
        else if (Input.GetMouseButtonUp(0) && selectTile != null)
        {
            DeployTile();
        }
    }

    private void SelectTile()
    {
        var mousePos = Input.mousePosition;
        mousePos.z = 10f;
        selectPos = defaultTilemap.WorldToCell(Camera.main.ScreenToWorldPoint(mousePos));

        if (!defaultTilemap.HasTile(selectPos)) return;

        for (int i = 0; i < placedTiles.Count; i++)
        {
            for (int j = 0; j < placedTiles[i].tileBundle.Count;j++)
            {
                if (placedTiles[i].tileBundle[j].x == selectPos.x && placedTiles[i].tileBundle[j].y == selectPos.y)
                {
                    selectTile = placedTiles[i];
                    break;
                }
            }

            if (selectTile != null) break;
        }

        for (int i = 0; i < selectTile.tileBundle.Count; i ++)
        {
            var pos = new Vector3Int(selectTile.tileBundle[i].x, selectTile.tileBundle[i].y, 0);
            moveTilemap.SetTile(pos, selectTile.tileBundle[i].tile);
            defaultTilemap.SetTile(pos, null);
        }
    }


    private void MoveTile()
    {
        var mousePos = Input.mousePosition;
        mousePos.z = 10f;
        Vector3Int nextPos = defaultTilemap.WorldToCell(Camera.main.ScreenToWorldPoint(mousePos));

        if (selectPos == nextPos) return;

        selectTile.tileBundle.ForEach(tb => { moveTilemap.SetTile(new Vector3Int(tb.x, tb.y, 0), null); });
        selectTile.tileBundle.ForEach(tb => {
            var pos = new Vector3Int(tb.x - (selectPos.x - nextPos.x), tb.y - (selectPos.y - nextPos.y), 0);
            moveTilemap.SetTile(pos, tb.tile);
            tb.x = pos.x;
            tb.y = pos.y;
        });

        selectPos = nextPos;
    }


    private void DeployTile()
    {
        selectTile.tileBundle.ForEach(tb => {
            var pos = new Vector3Int(tb.x, tb.y, 0);
            moveTilemap.SetTile(pos, null);
            defaultTilemap.SetTile(pos, tb.tile);
        });

        selectTile = null;
    }


    public class PlacedTiles {
        public string name;
        public List<TileBundle> tileBundle = new List<TileBundle>();

        public PlacedTiles(TileStore tileStore, int x, int y)
        {
            this.name = tileStore.name;
            for (int i = 0; i < tileStore.tiles.Length; i++)
            {
                this.tileBundle.Add(new TileBundle(tileStore.tiles[i], x, y-i));
            }
        }

        public class TileBundle
        {
            public Tile tile;
            public int x;
            public int y;

            public TileBundle(Tile tile, int x, int y)
            {
                this.tile = tile;
                this.x = x;
                this.y = y;
            }
        }
    }
}

MoveTileController.cs

tileSOに作成したScriptableObjectを、defaultTilemapに家具配置用Tilemapを、moveTilemapに移動用Tilemapを登録します。

f:id:hiyotama:20210327030736p:plain

基本的には【Unity】2Dタイルマップ12 Tileを掴んで、移動させて、配置するで作成したScriptと同じで、UpdateメソッドにてTileを掴む(SelectTile)、Tileを移動させる(MoveTile)、Tileを配置する(DeployTile)メソッドを呼び出しています。

StartメソッドにてSetFurnitureメソッドを呼び出し、ScriptableObjectに登録した家具をSceneにセットします。
家具をセットすると同時にPlacedTileクラスにTile情報を登録します。

PlacedTileクラスにはTileBundleというクラスのListがあり、TileBundleクラスにはTileとTileの位置情報が保存されます。
2マスで1TileのオブジェクトをPlacedTileクラスに保存する場合、TileBundleクラスには(x, y)と(x, y-1)の2つのTile位置情報が保存されます。
今回のtableタイルの場合はtable_fと(x:2, y:3)、table_rと(x:2, y:2)の情報が保存されます。

f:id:hiyotama:20210327032433p:plain

結果

それでは実際にTileを掴んで動かしてみます。

f:id:hiyotama:20210327032955g:plain

2マスで1オブジェクトのテーブルTileが2マスとも動いています。
もちろん1マスのタンスTileも正常に動作します。

f:id:hiyotama:20210327033136g:plain


今回は以上となります。
ありがとうございました〜。