タイルマップを用いた地形の判定(前編)
2022/12/17
Unity version : 2021.1.2.7f1 Personal(日本語化済み)

はじめに

キャラクターのようなオブジェクトをタイルマップの地形に乗せたいとします。
過去の記事で特定のタイル名を取得するを扱いましたので応用します。
結構な長丁場になりましたので今回はオブジェクトが主な地面に引っかかるまでを紹介します。


目次


準備

空のプロジェクトをから始めます。
タイルマップでタイルを組み合わせて地形を作ります。
ここでは、過去の記事を参考に用意します。


1.地形のタイルマップを用意する

  • 塗りつぶしのタイルが書かれたタイル画像を用意する
  • ヒエラルキーからTilemapオブジェクトを作成する
  • タイルマップで平らな地面を描く


2.乗せるもの(2Dオブジェクト)を用意する

  • ヒエラルキーから「2Dオブジェクト」→「スプライト」→「正方形」を選びます
  • 大きさを変えずにスクリーン上、地形より上側に配置します
  • 名前を"Box"に変更します
☆ここまででエラーがないか一度プレイボタンを押してみましょう。


3-1."Box"にスクリプトを付ける

"Box"が自由落下するスクリプトを作ります。

※Box.cs


作成したら"Box"オブジェクトに"Box.cs"スクリプトをアタッチします。
あとでタイルマップに乗せられるように修正していきます。


3-2.60fpsタイマーを作る

"Box"が自由落下するスクリプトを作りましたが、そのままではフレームレートが早すぎて高速落下してしまいます。
Unityでは標準で1/1000秒単位で処理を試みます。
今回はタイマーを作って時間を調節します。
"Time.deltaTime"を用いるのですが、汎用性を考えてタイマーを別スクリプトで作ります。
ここでは約60fps毎に更新フラグを出すような物を作成します。

※Time60.cs


作成したら空のオブジェクトを作り、オブジェクト名を"Time60"にします。
そのオブジェクトに"Time60.cs"スクリプトをアタッチします。


☆ここまででエラーがないか一度プレイボタンを押してみましょう。


4-1."Box"の下側に判定点を作りタイルマップにアクセスできるようにする

まず、タイルマップにアクセスできるように"Box.cs"に追記します。
※Box.cs(追記1)


次に、"Box.cs"が"Time60.cs"にアクセスし、60fpsのフラグが取得できるように"Box.cs"に追記します。
※Box.cs(追記2,3)


次に、"Box"オブジェクトの下側をチェックするように追記します。
※Box.cs(追記4,5,6、ここまでの全文)


※スクリプトを保存したらヒエラルキーの"Tilemap"をインスペクターの"Tilemap"に登録します。


4-2."Box"の下側に接触しているタイル番号を取得する

"Box"オブジェクトの下側に接触しているタイル番号を取得できるように追記します。

1.判定座標をグリッド座標に変換します。
Vector3Int targetPosInt = tilemap.WorldToCell(pos);

2.そのグリッド座標のスプライト情報を取得します。
Sprite spr = tilemap.GetSprite(targetPosInt);

3.タイルマップのスプライト名は<タイルマップ画像名>+<_番号>の形式なので、
"spr"の名前からテキスト形式の数字を取り出します。
(タイルが無い時は"spr"に"null"が入りますので別途処理します。)
if(spr != null)
str = spr.name.Substring( 8, spr.name.Length - 8); //"Terrain_"の文字を取り除く
else
str = "-1";

4.テキスト形式の数字を数値型(int)に変換します。
index = int.Parse(str);

ここまでのスクリプトは次のようになります。
※Box.cs


☆ここまででエラーがないか一度プレイボタンを押してみましょう。


5.地形に当たったら落ちないようにする

まず、地形から落ちなければ良いとします。
地形による位置補正を加えて落ちないようにします。
"Box"オブジェクトの下部が地形にめり込んでいたら、その分を戻すようにします。

ここで、Y軸のめり込み分を戻すことを考えます。
Y軸は画面上方向が”+”です。
地形と"Box"オブジェクトの関係は下図のようになります。


図で示したの関係から、めり込んだ分の長さ"dist"は、
dist = 1 - ( checkPos.y % 1)
となります。

以上を踏まえてスクリプトに追記します。

※Box.cs(全文)


ここで、エラーがないかも含めてプレイボタンを押します。

・・・どうでしょうか?
"Box"オブジェクトがタイルマップの地形に乗れば成功です。


おわりに

ここまでお疲れ様でした!
準備が長くなってしまいましたが、地形判定の基本形ができました。

タイルの判定と識別の部分はまだまだ改善できると思いますが、
今回はここまでにしたいと思います。

留意点としては、この方法だとガーベージコレクタが発生します
解決策があるかもしれませんが、次回もこの続きから始めたいと思います。
次は、坂道(スロープ)処理について私が解っている範囲で紹介します。

ここまでお読みいただき有難う御座いました。
また、参考になったサイトの皆さんに感謝申し上げます。

ページトップ


(付録)"Box"と接地したタイルの種類を確認できるようにする

タイルに接触したときのタイル番号を表示できるように、テキストUIを作ります。

  • ヒエラルキーから「UI」→「テキスト - TextMeshPro」を選びます
  • スクリーンに配置します。
  • 名前を"Text(TMP)"に変更します。※(TMP)は自動で付きます
以下のスクリプトを作成し、"Text(TMP)"オブジェクトにアタッチします。 ※SpriteText.cs


※インスペクターに"Box"オブジェクトを登録します。

ページトップ


参考サイト

【Unity】タイルマップ - Tilemapクラスでよく使う関数(コガネブログ様)
https://baba-s.hatenablog.com/entry/2018/04/08/131500#GetTile

Tilemapの情報をスクリプトから取得する【Unity】(にゃま様)
https://nyama41.hatenablog.com/entry/get_tilemap_info

そのほか沢山のサイト様、有難うございました。

ページトップ