【Unity】2Dタイルマップ12 Tileを掴んで、移動させて、配置する
Unity 2020.2.1f1 Personal(2021年3月)
前回の続きです!
今回はTileをクリックして掴んで、移動させて、マウスを離すとTileが配置される機能を実装します。
ゲームでは部屋や町などのエディットモードでオブジェクトを移動させる時に使います。
Tilemapを2つ作成する
まずはTilemapを2つ作成します。
1つはデフォルトのTileを配置しておくTilemap、もう1つはTileを掴んだ時にTileを少し浮かせるTilemapです。
TilemapはHierarchy > 2D Object > Tilemap Isometricから作成します。
名前は「DefaultTilemap」「MoveTilemap」とします。
MoveTIlemapのほうだけ2点設定を変えます。
まずはposition.yを0.1に変更します。
次にこの後作成するMaterialをTilemapRendererに設定します。
MaterialはProjectビュー > Create > Materialから作成できます。
名前を「SelectTileMaterial」にし、Shaderを「Sprites/Default」を選択し、
TintのAlpha(透明度)を0.7くらいに設定して下さい。
TilemapControllerスクリプト
前回作成したTilemapController.csの内容を変えていきます。
やりたいことは以下の通りです。
①Isometricモードで5 * 5のTileを自動生成
②クリックした時にTileを掴むメソッド作成(SelectTile)
③Tileを移動させるメソッド作成(MoveTile)
④マウスを話した時にTileを配置するメソッド作成(DeployTile)
まずは①から順番に見ていきます。
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.Tilemaps; public class TilemapController : MonoBehaviour { [SerializeField] Tilemap defaultTilemap; [SerializeField] Tilemap moveTilemap; [SerializeField] Tile blockTile; private void Start() { for (int y = 0; y < 5; y++) { for (int x = 0; x < 5; x++) { defaultTilemap.SetTile(new Vector3Int(x, y, 0), blockTile); } } } private void Update() { } }
TilemapController.cs
Isometricモードで、SetTileメソッドで5 * 5のTileを自動生成しています。
前回の記事で詳しく解説していますのでご参照下さい。
続いて②です。
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.Tilemaps; public class TilemapController : MonoBehaviour { [SerializeField] Tilemap defaultTilemap; [SerializeField] Tilemap moveTilemap; [SerializeField] Tile blockTile; private Tile selectTile; private Vector3Int originCellPos; private Vector3Int selectCellPos; private void Start() { for (int y = 0; y < 5; y++) { for (int x = 0; x < 5; x++) { defaultTilemap.SetTile(new Vector3Int(x, y, 0), blockTile); } } } private void Update() { if (Input.GetMouseButtonDown(0)) { SelectTile(); } } private void SelectTile() { var pos = Input.mousePosition; pos.z = 10f; selectCellPos = defaultTilemap.WorldToCell(Camera.main.ScreenToWorldPoint(pos)); originCellPos = selectCellPos; var getTile = defaultTilemap.GetTile<Tile>(selectCellPos); if (getTile) { moveTilemap.SetTile(selectCellPos, getTile); defaultTilemap.SetTile(selectCellPos, null); selectTile = getTile; } } }
TilemapController.cs
画面をクリックした時にSelectTileメソッドが呼ばれます。
TilemapのWorldToCellメソッドにクリックした位置(WorldPoint)を渡すと、TilemapのCell位置が返ってきます。
originalCellPosは、Tileを動かした先に既にTileがあった場合にリセットする時用に位置を保存しています。
GetTileメソッドでクリックしたTileを取得します。
Tileがnullではなかったら、SetTileメソッドでMoveTilemapへ移動させます。
SetTileメソッドの第二引数にnullを指定するとTileを削除できるので、DefaultTilemapのほうのTileは削除します。
続いて③です。
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.Tilemaps; public class TilemapController : MonoBehaviour { [SerializeField] Tilemap defaultTilemap; [SerializeField] Tilemap moveTilemap; [SerializeField] Tile blockTile; private Tile selectTile; private Vector3Int originCellPos; private Vector3Int selectCellPos; private void Start() { for (int y = 0; y < 5; y++) { for (int x = 0; x < 5; x++) { defaultTilemap.SetTile(new Vector3Int(x, y, 0), blockTile); } } } private void Update() { if (Input.GetMouseButtonDown(0)) { SelectTile(); } else if (Input.GetMouseButton(0) && selectTile) { MoveTile(); } } private void SelectTile() { var pos = Input.mousePosition; pos.z = 10f; selectCellPos = defaultTilemap.WorldToCell(Camera.main.ScreenToWorldPoint(pos)); originCellPos = selectCellPos; var getTile = defaultTilemap.GetTile<Tile>(selectCellPos); if (getTile) { moveTilemap.SetTile(selectCellPos, getTile); defaultTilemap.SetTile(selectCellPos, null); selectTile = getTile; } } private void MoveTile() { var pos = Input.mousePosition; pos.z = 10f; Vector3Int nextPos = defaultTilemap.WorldToCell(Camera.main.ScreenToWorldPoint(pos)); if (selectCellPos != nextPos) { moveTilemap.SetTile(nextPos, selectTile); moveTilemap.SetTile(selectCellPos, null); selectCellPos = nextPos; } } }
TilemapController.cs
Updateメソッドでクリックしっぱなしの時(Input.GetMouseButtonメソッド)、またselectTileがnullでない時、MoveTileメソッドを実行し続けます。
MoveTileメソッドでは現在フレームでのCell位置(nextPos)と1つ前のフレームのCell位置(selectCellPos)を比較し、違っていたら新しいCell位置にselectTileをセットし、古いCell位置のTileを削除します。
Tileを移動させた場合、selectCellPosを更新します。
最後に④です。
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.Tilemaps; public class TilemapController : MonoBehaviour { [SerializeField] Tilemap defaultTilemap; [SerializeField] Tilemap moveTilemap; [SerializeField] Tile blockTile; private Tile selectTile; private Vector3Int originCellPos; private Vector3Int selectCellPos; private void Start() { for (int y = 0; y < 5; y++) { for (int x = 0; x < 5; x++) { defaultTilemap.SetTile(new Vector3Int(x, y, 0), blockTile); } } } private void Update() { if (Input.GetMouseButtonDown(0)) { SelectTile(); } else if (Input.GetMouseButton(0) && selectTile) { MoveTile(); } else if (Input.GetMouseButtonUp(0) && selectTile) { DeployTile(); } } private void SelectTile() { var pos = Input.mousePosition; pos.z = 10f; selectCellPos = defaultTilemap.WorldToCell(Camera.main.ScreenToWorldPoint(pos)); originCellPos = selectCellPos; var getTile = defaultTilemap.GetTile<Tile>(selectCellPos); if (getTile) { moveTilemap.SetTile(selectCellPos, getTile); defaultTilemap.SetTile(selectCellPos, null); selectTile = getTile; } } private void MoveTile() { var pos = Input.mousePosition; pos.z = 10f; Vector3Int nextPos = defaultTilemap.WorldToCell(Camera.main.ScreenToWorldPoint(pos)); if (selectCellPos != nextPos) { moveTilemap.SetTile(nextPos, selectTile); moveTilemap.SetTile(selectCellPos, null); selectCellPos = nextPos; } } private void DeployTile() { moveTilemap.SetTile(selectCellPos, null); if (defaultTilemap.HasTile(selectCellPos)) { defaultTilemap.SetTile(originCellPos, selectTile); } else { defaultTilemap.SetTile(selectCellPos, selectTile); } selectTile = null; } }
TilemapController.cs
Updateメソッドでマウスを離した時(Input.GetMouseUp)、DeployTileメソッドを実行します。
まずはmoveTilemapのTileを削除します。
Tilemap.HasTileメソッドにCell位置を渡すとTileがあるかをtrue/falseで返してくれます。
trueの時はTileが元あった位置(originCellPos)にselectTileを戻します。
falseの時は移動させたい位置(selectCellPos)にselectTileを配置します。
最後にselectTileをnullにします。(nullにしないとInput.GetMouseButtonとInput.GetMouseButtonUpが意図せぬタイミングで実行されてしまう)
結果
以上でTilemapController.csの設定は完了です。
InspectorからDefaultTilemap, MoveTilemap, BlockTileを設定します。
BlockTileについては前回までに作成しているのでそちらをご活用下さい。
それでは結果を見ていきます。
Tileを掴み、移動させ、配置することができています。
また移動先に既にTileがある場合は元の位置に戻されます。
今回は以上になります。
ありがとうございました〜。