Tilemapの実装確認とフィールドマップを作る話


この記事は[Unity #2 Advent Calendar 2017](https://qiita.com/advent-calendar/2017/unity2)の記事です。
前日は@sakuo_sundayさんの[「Rayが当たったゲームオブジェクトの色を変化させる」]()です。

## はじめに

ようやくTilemapがきましたね。
最初に発表があってから、Previewとか弄って待ち焦がれること早行く数年でした。
ExperimentalPreview3(以下EP3)あたりで、真面目に触ってみてゲームを作ろうと思ったのですが、なんか出力が上手くいかずUnityブルーの画面をただ眺めるものが出来上がって弄るのを止めたのは良い思い出です。

しかし、正式リリースなので、そんな思い出話とはおさらばです！
最近は3Dモデリングに傾倒していて、にわか3Dモデラーになっていたのですが、そろそろ技術的な何かをしたくなってきて柄にもなくアドカレに参加してみました。
最初の一歩な記事を書こうとも考えたのですが、Unity道場が公式でそんなもくろみを打ち砕く資料をだしてきたので、ちょっと趣を変えていこうと思います。

[【Unity道場】使って覚えるTileMap](https://www.slideshare.net/UnityTechnologiesJapan/tilemap)
ちなみに資料はこちら。
よく書かれています（当然）

では、閑話休題。


## 状況を確認

Unityが公式でサンプルとして提供しているのは[RoboDash](https://github.com/Unity-Technologies/2d-gamedemo-robodash)で、Githubから自由に落とすことが出来ます。
まずサンプルをみて追いかけてなかった時期の知識を埋めようかななんて思います。
Previewの時はテクスチャからスライス設定をして、そこからタイルを作って、シーン上のタイルマップに配置するような流れでしたが、そこは変わっていないようです。

ちょっとパレットのUIが変わったようですが、誤差のうちかな。

RoboDashの中身を見ていると、やはりブラシをカスタマイズしているので、作業の効率化を図る為にはブラシのカスタムは必須なのかなとか思います。
[Tiled](http://www.mapeditor.org/)とかの terrainブラシなんか最初から実装されたりしないものかと思いましたが、ないのですね残念。
ポジティブに考えれば、凄くバニラな状態でやりたい放題と言える状況なのかも知れません。

またリファレンスには[2d-extras](https://github.com/Unity-Technologies/2d-extras)というプロジェクトがGithubにあるよというアナウンスもされています。
中身をみたらTerrain TileとかRule Tileとか美味しそうなのが見えます。
上でバニラだなぁっていう部分を補完してくれるポジションのプロジェクトなのかもしれません。
ちょっと中身を見てみましょうか。

## Terrain Tile
メニューからタイルのアセットを作ってみると分かるのですが、設定する項目がずらりとでてきます。
自分のタイルとその周辺のタイルがどうなっているかによって配置されるタイルが変わるという、Uniteとかのデモで見かけたやつですね。
EP3の時も見かけたような気がします。

[2d-techdemos](https://github.com/Unity-Technologies/2d-techdemos)のTrrain Tileのシーンをみるとわかりやすいかと思います。

設定する項目が全部で13個もあって、正直どれがどれだろうという気持ちになりますね。
これだけ見て設定出来る人っているのかしら、と首を傾げてしまいます。
タイルは必要に応じて回転されて配置されます。

## Rule Tile
ちょっと不便ですよねという不安を払拭してくれるのがこっちのタイルです。
Terrain Tileはコーディングされていることが多かったのですがRule Tileはエディタで視覚的に設定できるようになっています。
2d-techdemosのCaveというタイルアセットをInspectorで表示するとわかるのですが、Terrain Tileでずらっと並んだ項目を視覚的に設定できるようになっています。
また、条件が成立したときに、出力するタイルをランダムに出来たり、アニメーションするように出来たりと、Terrain Tileよりちょっと高機能になっていますね。

見た感じではRule TileがあるならTerrain Tileは使わなくてもいい感じかな・・・。

こちらで既に試している人もいまして、詳しく説明されているので、うちのざっくりした話よりより理解が深まるかと思います。
[Unity2017.2向けTilemap周りを試したので概要と感想](https://qiita.com/keidroid/items/096491b7692ea7d1a4f1)

## Scriptable TilesとScriptable Brushes
ここまで話をしてきたユーザーがカスタマイズすることができるタイル・ブラシのことを公式では表題のように呼んでいます。
タイルはタイルが設定されるときとか、タイル自体の挙動を設定することができるものですが、ブラシの方は配置するものをどうするは当然ですが、塗りや削除などの挙動自体も変えることが出来る様です。
[公式のサンプル](https://docs.unity3d.com/Manual/Tilemap-ScriptableBrushes-Example.html)ではラインを引くようにタイルを置くことが出来るブラシを作っています。

## せっかくだから何か配置しよう
紹介文しか書いてない気がするので、自分がきっと作るであろうことを見越して手を動かしてみます。

マップチップを使ってワールドマップを作ったりしようと思います。
そんなわけで手頃なフリー素材を準備いたします。
1マスは40ドットなので、Pixel Per Unitを40にします。
![ppu40.PNG](https://qiita-image-store.s3.amazonaws.com/0/54312/fbae6c59-2ace-b600-4349-2b58e34940d5.png)


次はRuleTileの設定です。
当然のことながらRuleTileの設定を考慮したフリー素材なんかあるわけがなくてですね、置く度にあーこれが足りないのね　と切り貼りしてマップチップをこさえてみました。
![tile_ruletile.PNG](https://qiita-image-store.s3.amazonaws.com/0/54312/d855a70a-ee35-db7a-3ad1-ccde7f9cd03c.png)

（回転とかで対応されるので結合部分が汚くなっているのは、素材制作者に申し訳ない）

Tiledをちょっと弄っていたときがあったので、Unityのタイル設定にはちょっと違和感を感じました。
前者は自分が置くタイル周辺を書き換えるような仕組みに対して、Unityの方は置くタイルの周辺で自分を書き換えるので、最初RuleTileも？　でした。
癖を押さえてしまえば、まぁ、どっちでも問題ない話ですね。

では、プログラマらしくプログラマブルに地形を設定してみましょうか。
タイルマップを海で埋めてしまいましょう。

Tilemap.BoxFill( Vector3Int.zero, sea, 0, 0, size.x, size.y );

こんな感じで海で塗りつぶしてみたら・・・

![tile_worldend.PNG](https://qiita-image-store.s3.amazonaws.com/0/54312/1ba4a4cc-ffd2-70b1-09b6-82b57482998b.png)

・・・・あ、うん、そうね。
同じタイルかという判定なのだから、当然端はそうなるよねぇ。
RuleTileでどうしたらいいか思いつかないから世界の端は地面にしますね。

ノイズから真面目に地形の高低とか考えて生成しようかなぁとか思いましたが、時間がなくなってきたので、すいません。適当に種を配置してそこから成長させるくらいのマップ生成でお茶を濁します。
![tile_generate.PNG](https://qiita-image-store.s3.amazonaws.com/0/54312/66cea1b7-ac9e-f835-9e09-d440d3cf4df2.png)


なんかそれっぽい形になったのでよしとしましょう。
当然ですがRuleTileをプログラムから設置してもきちんと設定したルールに従って表示しているスプライとを切り替えてくれます。

![tile_forest_random.png](https://qiita-image-store.s3.amazonaws.com/0/54312/3fd953e8-f2b4-0f61-dd59-5ceaac3eb6af.png)

森の形は小さいのと大きいなのをランダムで出るようにRuleTileでランダムを指定しました。

キャラクターもざくざく作って、アニメーションのパターンを設定して、方向に合わせて変わるようにBlendTreeで設定しました。
（floatなのに整数値の入力を期待しているところに危うさを感じましたが、問題なく動いていました）

カーソルキーで動くようにして、カメラも合わせて動かしていくと、当然の様に世界の端にたどり着きます。

![tile_world_end.PNG](https://qiita-image-store.s3.amazonaws.com/0/54312/e959d471-3d64-44aa-84f9-02450349dbd4.png)

これをループさせようと思います。
一番簡単に思いつくのはカメラをマップの反対側を描画して、レンダリングで合成するという方法です。
X軸とY軸の反対側と、その二つのカメラの隙間を埋めるカメラを用意します。
![tile_camera4.PNG](https://qiita-image-store.s3.amazonaws.com/0/54312/9cc891f5-f63c-2e68-a437-e301eb7b1cb0.png)

なんかタイルマップなのにカメラが四つも必要なの？　という気持ちがあるわけですが、他にループするいい手法がある人は教えてください。

![tile_camera_preview.png](https://qiita-image-store.s3.amazonaws.com/0/54312/1ba45000-82be-f602-d29c-ebd5dfcb1d95.png)
それぞれのプレビューを確認するとこんな感じです。

データ用のタイルマップを用意して、描画用のタイルマップに書き換え続けるという手法も考えたのですが、今回は見送りました。

海のタイルだけ移動出来なくしました。
地形マネージャーをきちんと作って、タイルに歩行可能設定をして、入力を受け取ってマネージャーにそちらの方向へ歩けますか？　という問い合わせをして移動判定をするのがいいと思うのですが、今回はそういうのなしで作ってしまったのでプレイヤーが判定しています。
色々と作りがまずいなと思うところは、サンプルということで許してください。まさかりは勘弁デス。

また、Tilemapオブジェクトを増やすとレイヤーのようなことが出来るので、地面＋建物の絵を用意するのではなくて、建物の背景を透過させておくと地面のパターンだけ建物を用意するとかそういうことはしなくてよくなります。
それも今回は見送っていて、平地の地面＋建物をあらかじめ用意して対応しました。
SortingLayerとOrder in Layerとかを弄ると前後が調整できます。この辺はいつもと同じ感じですね。

## あとがき

Unity 2017.2.0f3を使用しています。
マップチップやキャラクターなどの素材は[ぴぽや様](http://blog.pipoya.net/)のフリー素材を使っています。

古い世代の人間なので、どうしてもタイルマップをみるとフィールドを作ってうろうろとさせたくなります。
期待して待っていた機能なので、もっと使い倒して何か形になるものを発表したいですね。
読み返してみたら全然コードを貼っていませんね。
でも、正直貼るような内容のものがないというか……　大体がエディタ操作で出来てしまうんですよね。あんまり大したものではないですが、Githubの方に[プロジェクト](https://github.com/mikenekoworks/Tilemap1)をあげておこうと思います。

明日は@Saseさんの「[【Unity】ロープのスペシャリストになれるアセットObi Rope](https://qiita.com/Sase/items/0debe55ad0d80374a36a)」です。


## おまけ
![tile_omg.png](https://qiita-image-store.s3.amazonaws.com/0/54312/d88966a5-306c-f7c4-e03a-9df1c3d4eaf5.png)

ただのランダムだから当然こうなる時もある。