Tilemap(タイルマップ)の使い方!タイルパレットの作成から当たり判定まで

2Dゲームでマップを作るとき、スプライトを1枚ずつ並べていくのはとても大変・・・そんなときに使いたいのがTilemap!お絵かきソフトのようにマス目を塗るだけでマップが作れます。この記事は以前書いた基本編を、Unity6.3 LTSの画面に合わせて書き直しました。タイルパレットの作成から、塗り方、当たり判定、スクリプトでタイルを置く方法までまとめてご紹介します!

今回作るマップ。草の地面に土の道と池があり、まわりをレンガの壁が囲んでいる
目次

Tilemapでどんなことが出来る?

  • グリッド(マス目)にスプライトを塗るように配置出来る
  • グリッドの形を選べる
    • Rectangle:四角。一番よく使う
    • Hexagonal:六角形(Point Top/Flat Top)
    • Isometric:ひし形のクォータービュー(Isometric/Isometric Z as Y)
  • 塗ったタイルにまとめて当たり判定を付けられる
  • Rule Tileを使うと、隣のタイルに合わせて自動で形が変わる道や地面が作れる

今回は基礎中の基礎、Rectangle(四角)のTilemapを使います。

プロジェクトの確認

  • Unityのバージョンは6.3 LTS
  • テンプレートは2D(Universal 2D)
    • 2D Tilemap Editorと2D Tilemap Extrasは最初から入っています
  • タイル用の画像(今回は16×16ピクセルのタイルを横8×縦4に並べた画像を使います)
    • 手元にない人はAsset Storeで「tileset」と検索すると、無料のものがたくさん見つかります

タイルの画像を準備しよう

スプライトの設定

タイル用の画像をAssetsにドラッグ&ドロップして、インスペクターで下記のように設定します。

  • Texture Type:Sprite (2D and UI)
  • Sprite Mode:Multiple(1枚の画像に複数のタイルが並んでいる場合)
  • Pixels Per Unit:タイル1枚のピクセル数(16×16なら16)
  • Filter Mode:Point (no filter)
  • Compression:None

最後にApplyを押します。

タイル画像のインポート設定。Sprite ModeがMultiple、Pixels Per Unitが16、Filter ModeがPoint (no filter)、CompressionがNone

Pixels Per Unitはタイル1枚のピクセル数と同じにしておくと、タイル1枚がちょうど1マス(1ユニット)の大きさになります。

スライム

Pixels Per Unitがタイルのサイズと合っていないと、タイルとタイルの間に隙間が出来たり、重なったりします・・・ドット絵ならFilter ModeをPointにするのも忘れずに

Sprite Editorでタイルを切り分ける

1枚の画像にタイルが並んでいる場合は、Sprite Editorで1マスずつに切り分けます。

  • インスペクターのOpen Sprite Editorを押す
  • 左上のSliceを開く
    • Type:Grid By Cell Size
    • Pixel Size:X 16 / Y 16
  • Sliceボタンを押す
  • 右上のApplyを押す
Sprite EditorでSliceのメニューを開いた状態。TypeがGrid By Cell Size、Pixel Sizeが16と16で、画像がマス目に切り分けられている

切り分けたスプライトには、tileset_0、tileset_1・・・のように左上から順番に名前が付きます。

Sliceボタンを押しただけでは、まだ保存されていません。右上のApplyを押すのを忘れると、Sprite Editorを閉じたときに切り分けが元に戻ってしまいます。

タイルパレットを作ろう

タイルパレットは、塗るときに使う「絵の具のパレット」のようなものです。

  • Window>2D>Tile Paletteでタイルパレットウインドを開く
  • タイルが並ぶところのすぐ上のプルダウンから、Create New Tile Paletteを選択
    • Name:MapPalette
    • Grid:Rectangle
  • Createを押して、保存するフォルダを選ぶ(Assets/Tilemap/Palettesなど)
Create New Paletteの小さいウインド。NameにMapPalette、GridにRectangleが入っていて、Createボタンがある

パレットが出来たら、切り分けたスプライトをタイルパレットウインドにドラッグ&ドロップします。タイルアセットの保存先を聞かれるので、Assets/Tilemap/Tilesなどのフォルダを選べばOKです。

タイルパレットウインド。上にツールが並び、その下に塗り先のプルダウン、MapPaletteにタイルが画像と同じ並びで置かれている

スプライトをドラッグ&ドロップすると、1枚ごとにタイルアセット(.asset)が作られます。シーンに塗るのはこのタイルアセットで、元の画像を直接塗っているわけではありません。

シーンにTilemapを置いて塗るッ!

Tilemapを追加

  • GameObject>2D Object>Tilemap>Rectangularを選択
    • HierarchyにGridと、その子どものTilemapが作られる

Gridがマス目のサイズを、Tilemapが塗ったタイルの情報を持っています。

タイルを塗る

  • タイルパレットウインドの塗り先のプルダウン(Active Target)がTilemapになっていることを確認
  • パレットの中から塗りたいタイルをクリックして選択
  • Sceneビューでクリックやドラッグをすると、タイルが塗られる

下図のように塗れたら成功!

左のタイルパレットで草のタイルを選んで地面を塗り、Box Fillで土の道と池を四角くまとめて塗っていく様子

ドラッグするだけで地面が広がっていくので、マップ作りがかなり楽しくなります。広い範囲はBox Fillでまとめて塗ると早いです。

よく使うツールとショートカット

タイルパレットウインドの上に並んでいるツールは、ショートカットで切り替えられます。覚えておくと作業がかなり楽になります。

タイルパレットウインドの上に並んだツールのボタン。左からSelect・Move・Paint・Box Fill・Pick・Erase・Flood Fill・回転・反転
  • Select(S):範囲を選択
  • Move(M):選択した範囲を移動
  • Paint(B):1マスずつ塗る
  • Box Fill(U):四角い範囲をまとめて塗る
  • Pick(I):Sceneビューのタイルを拾って、そのタイルで塗れるようにする
  • Erase(D):消しゴム
  • Flood Fill(G):囲まれた範囲を塗りつぶす
  • 塗る前に「[」「]」キーでタイルを回転

個人的に一番使うのはPick(I)です。Sceneビューで同じタイルを塗りたいとき、パレットから探し直さなくて済みます。

レイヤーを分けて重ねよう

地面・装飾・壁のように、Tilemapを分けておくと後から編集しやすくなります。当たり判定を付けたいのは壁だけ、ということも多いです。

  • Hierarchyで、Gridの中のTilemapを複製して名前を付ける
    • Ground:地面
    • Decoration:草や花などの飾り
    • Wall:壁
  • それぞれのTilemap RendererのOrder in Layerを設定
    • Ground:0
    • Decoration:1
    • Wall:2
  • 塗るときは、タイルパレットウインドの塗り先のプルダウンで塗り先を切り替える
左はHierarchyで、Gridの子にGround・Decoration・Wallの3つのTilemapが並んでいる。右はタイルパレットウインドで、塗り先がDecorationになっている

塗り先を切り替え忘れると、飾りの花を地面のTilemapに塗ってしまいます。塗る前にプルダウンの名前を見るクセを付けておきましょう。

当たり判定を付けよう

壁のTilemapに当たり判定を付けます。

  • WallのTilemapにTilemap Collider 2Dを追加
  • 同じオブジェクトにComposite Collider 2Dを追加
    • Rigidbody 2Dも自動で追加される
  • Rigidbody 2DのBody Type:Static
  • Tilemap Collider 2DのComposite Operation:Merge
左はSceneビューで、壁のまわりに緑の当たり判定の線が出ている。右はWallのインスペクターで、Rigidbody 2DのBody TypeがStatic、Tilemap Collider 2DのComposite OperationがMerge

Composite Collider 2Dを使うと、1マスずつバラバラだった当たり判定が1つにまとまります。

フェアリー

まとめておくと、壁のつなぎ目でプレイヤーが引っかかりにくくなるよ!

古い記事を見ながら作っている人へ
  • 古いバージョンの記事では「Used By Composite」にチェックを入れる手順になっています
  • Unity6.3ではComposite Operationのプルダウンに変わっていて、Mergeを選ぶのが同じ意味です
  • Body TypeをStaticにしないと、再生したときに壁が下に落ちていきます

スクリプトでタイルを置いたり消したりする

ゲーム中にタイルを置いたり、そのマスにタイルがあるか調べたり出来ます。ここではクリックしたマスにタイルを置く・消すスクリプトを作ってみましょう。InputSystemはUnity6でInputSystemを使うチュートリアルで作ったInputSystem_Actionsを使っています。

using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.Tilemaps;

public class TileClicker : MonoBehaviour
{
    [SerializeField] private Tilemap tilemap;
    [SerializeField] private TileBase tile;

    private InputSystem_Actions inputActions;

    private void Awake()
    {
        inputActions = new InputSystem_Actions();
    }

    private void OnEnable()
    {
        inputActions.Enable();
    }

    private void OnDisable()
    {
        inputActions.Disable();
    }

    private void Update()
    {
        if (!inputActions.Player.Attack.WasPressedThisFrame())
        {
            return;
        }

        Vector3 worldPosition = Camera.main.ScreenToWorldPoint(Mouse.current.position.ReadValue());
        Vector3Int cell = tilemap.WorldToCell(worldPosition);
        // カメラのZ座標が入ってしまうので、Tilemapと同じ0にそろえる
        cell.z = 0;

        // タイルがあれば消して、なければ置く
        tilemap.SetTile(cell, tilemap.HasTile(cell) ? null : tile);
    }
}

空のゲームオブジェクトに追加して、インスペクターで下記を設定します。

  • Tilemap:タイルを置きたいTilemap(今回はDecoration)
  • Tile:置きたいタイルアセット(今回はキノコのtileset_15)
    • タイルパレットにドラッグしたときに作られたものです

スクリプトのポイントをいくつか補足

  • WorldToCellでワールド座標をマス目の座標に変換
    • Tilemapの位置はVector3Intのマス目で扱います
  • SetTileでタイルを置く・消す
    • nullを渡すと、そのマスのタイルが消えます
  • HasTileでタイルがあるか調べる
    • 同じ仕組みで「このマスは壁か?」のような判定も作れます
  • クリックはPlayer.Attackで受け取る
    • 初期状態のInputSystem_Actionsでは、Attackにマウスの左ボタンが割り当てられています

再生して左クリックで、タイルが置けたり消えたりすれば成功!

Gameビューで何もないマスをクリックするとキノコのタイルが置かれ、置いたマスをもう一度クリックすると消える様子
  • 何もないマスをクリックすると、キノコのタイルが置かれる
  • 置いたマスをもう一度クリックすると、タイルが消える
  • 塗っておいた地面や壁のタイルは、Decorationとは別のTilemapなので消えない

Tilemapは「マス目の座標でタイルを出し入れする仕組み」と覚えておくと、ステージの自動生成やパズルゲームにもそのまま使えます。

うまくいかないときは

症状確認するところ
タイルの間に線や隙間が出るPixels Per Unitがタイルのサイズと同じか。Filter ModeがPointか。それでも出る場合はSprite AtlasやPixel Perfect Cameraを使う
タイルが大きすぎる・小さすぎるPixels Per Unit
塗れないタイルパレットウインドの塗り先のプルダウン。Paintツールが選ばれているか
当たり判定が効かないプレイヤー側にもRigidbody 2DとCollider 2Dが付いているか。Composite OperationがMergeか
スクリプトで置いたタイルが見えないcell.zを0にしているか。Tilemapに設定したのが見えているTilemapか

Gameビューを縮小して表示していると、タイルのつなぎ目にうっすら線が見えることがあります。Scale(倍率)を1xにしたり、ビルドして確認すると消える場合は、表示の縮小によるものなので気にしなくて大丈夫です。

次のステップ

今後のゲーム制作の記事でも、2Dのマップは基本Tilemapで作っていく予定です。

スライム

マップ作りを始めると、気づいたら何時間も経ってる・・・

フェアリー

楽しくなってきたら成功のサインだね!作ったマップはぜひSNSで見せてね!

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

コメント

コメントする

目次