[Unity備忘録] 2Dスクロールアクションを作る。
突如、天啓を得て、2Dスクロールアクションゲームを作りたくなった。Unityで。
"ゲームの作り方"の記事は探せばいくらでもあるけれど、索引的な意味も込めて記事に。
プロジェクトの作成
New Project>2D(Built-in RenderPipeline)でプロジェクトを作成。
(超要約)
2D(Built-in RenderPipeline)は細かいカスタマイズが可能だよ。最適化は自分でやってね。
Universal2Dは最適化を勝手にしてくれるよ。細かいカスタマイズはできないよ。
2D(Built-in RenderPipeline)が従来のレンダーパイプラインらしい。
マップの作成
マップ作成の流れは以下。
タイルパレットを用意する。
タイルパレットからタイルを配置して、マップを作成する。
UnityのAsset Storeからマップタイルをお借りする場合、大抵タイルパレットも用意されている。自作のマップタイルを使いたいという奇特な方は、自分でタイルパレットを作成する必要がある。
デモを動かす
画面上、Window>Asset StoreからCainos様のPixel Art Platformer - Village Propsをお借りした。Package Managerからimportすると、Assets下にCainosフォルダが現れる。
Cainos>Pixel Art Platformer - Village Props>Scene>SC Demo Sceneを動かしてみる。 Scene画面でカメラを動かせば、Game画面に反映される。

タイルパレットの作成
window>2D>Tile PaletteでTile Paletteウインドウが開く。Create New Tile Paletteでタイルパレットを作成。
タイル.pngをAssetsの適当な場所に放り込んで、Pixels Per Unitを設定。その後、Tile Paletteウインドウに放り込んで、配置すればOK。

一枚の画像ファイルを切り分けるときは、Sprite ModeをMultipleに、Sprite Editorを開いてSlice。
複雑な切り分けも出来るみたいね。

参考
- 【Unity】2Dタイルマップ① 基本的な使い方
- Unityでタイルマップ(スプライト)の分割方法がわからなかった件
タイルの配置
SampleScene下に2D Object> でMap\Groundオブジェクトを作成。タイルパレットのブラシを駆使してマップを作っていく。
デモを参考にMap\Grassオブジェクトを作成。その子オブジェクトとして草を配置してみた。

2D Object>TilemapでGrassオブジェクト作るとコンポーネントにTilemapとTilemap Rendererがついてくるが、使わないなら消すが吉。
プレイヤーの作成
SampleScene下にPlayerオブジェクトを作成。プレイヤーの画像を放り込む。C#スクリプトでキー操作処理を記述、アタッチ。
参考
- Unity 2D横スクロールアクションゲームの作り方2 キャラクターを左右に移動させる 当たり判定も実装
プレイヤーの画像に32x32のdot絵を自作したのだが、ぼやけている。取り合えず画像のFilterをPointに、ComparisonをNoneに設定すればいいらしい。
詳しいことはこちらに。
- 2D Pixel Perfect

重力
Rigidbody 2Dコンポーネントをアタッチすると、オブジェクトは重力の影響を受けるようになる。影響を消したいなら、Body TypeをDynamic->Kinematicに変更すること。
お好みでFreeze Rotation Zにチェック。回転しなくなる。
重力の強さの調整はEdit>Project SettingからPhisics 2DでGravityのYをいじる。
衝突判定
PlayerにBox Collider 2Dコンポーネントをアタッチ。地面の方にも、Box Collider 2Dをアタッチすれば衝突判定を行うことができる。
とはいえ、一つ一つのタイルに衝突判定を付けるのは大変。そこで、Tilemap Collider 2Dでタイルにまとめて衝突判定を付与する。

……壁に引っかかる挙動が気になる。
Project(デフォルトだと画面下部)、Create>2D>Physics MaterialでZeroFrictionマテリアルを作成。Frictionを0に。これをPlayer\Box Collider 2Dのマテリアルに設定する。壁に引っかかるのは、摩擦のせいなのね。

これで、壁に引っかからず落ちるようになった。
地面のコリジョンを正方形に揃えたいなら、タイルのColliderTypeをGridに変更すること。
ColliderTypeについて、詳しくはここ、Tilemap Collider 2D。
ジャンプ
空中ジャンプを許すわけにはいかないので、接地判定を作る必要がある。
Player下に空のオブジェクトとしてGroundCheckを作成。Box Collider 2Dをアタッチして、Player足元に衝突判定を作る。Triggerにチェック。

Triggerにチェックを入れると、そのBoxは衝突しなくなり、代わりにオブジェクトが重なっていると、"何か"を起こすことができる。具体的には、C#スクリプトに記述した以下のメソッドが呼び出される。
(超要約)
以下の条件でメソッドが呼ばれる。
- OnTriggerEnter2D: 何かが判定に入ったとき。
- OnTriggerStay2D: 何かが判定に入り続けているとき。
- OnTriggerExit2D: 何かが判定から抜けたとき。
これでGroundCheckオブジェクトが地面と重なっていることを判定すればいいわけだ。
接地判定、ジャンプの具体的なコードはここを参考に。
- 【UnityでC#】スクリプトで接地判定を作ろう!
- 【UnityでC#】スクリプトで接地判定を作ろう!(続き)
補足。C#スクリプトのPublic変数は、Inspecterから設定できる。
これで、他クラスをインスタンス化し、その関数を扱える。

最後、オブジェクトにタグを付けるのを忘れずに。デフォルトだとGroundタグは無いので、作る。
これで、ジャンプ処理ができた。

稀に起きる二重ジャンプが気になる。接地判定が二重に行われたのが原因か?
Ground\Tilemap Collider 2D のUse By Compositeにチェック。Composite Collider 2Dをアタッチ。おまけで付いてきた、Rigidbody 2DのBody TypeをDynamic->Kinematicに。これで、タイルの衝突判定が一つに統合され、二重に接地判定が行われるのを防ぐ。
最終的なSampleScene下はこんな感じ。Grass下は適当。

ここまで作って、Unityの基本的な機能については、分かってきた気がする。
……言い過ぎである。レモンティーでも飲んで、落ち着くのだ。
プレイヤーのdot絵の描き方は、こちらが参考になります。
- 【32×32ドット絵】アクションゲーム風キャラクターの描き方
