【Unity】2Dタイルマップ17 2マスで1オブジェクトのTileを掴んで、移動させて、配置する
Unity 2021.1.0f1 Personal(2021年3月)
今回は以前投稿した【Unity】2Dタイルマップ12 Tileを掴んで、移動させて、配置するをアップデートします!
長テーブルなど2マスで1オブジェクトを表すTileを上記記事と同様に移動させていきます。
2マスで1オブジェクトのTileを準備する
今回は長テーブルのスプライトを用意しました。
table_f.png
table_r.png
過去記事を参考にTilePaletteへ登録します。(前回記事で使ったタンスも残しておきます。)
2マスで1オブジェクトのTile情報を保存できるScriptableObject
Tile情報を保存したScriptableObjectを過去記事で作成しました。
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の順番)
ScriptableObjectにTileを登録
以上でScriptableObjectの準備は完了です。
Tilemapを作成する
続いてTilemapを作成します。
家具配置用のTilemap(FurnitureTIlemap)と移動用のTilemap(MoveTilemap)を作成します。
移動用のみposition.yを0.1にします。
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を登録します。
基本的には【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)の情報が保存されます。
結果
それでは実際にTileを掴んで動かしてみます。
2マスで1オブジェクトのテーブルTileが2マスとも動いています。
もちろん1マスのタンスTileも正常に動作します。
今回は以上となります。
ありがとうございました〜。