Unity簡単2Dゲームの作り方【第4回】敵の作成と踏みつけ判定・バウンド処理を実装する | Unity入門の森 ゲームの作り方

Unity簡単2Dゲームの作り方【第4回】敵の作成と踏みつけ判定・バウンド処理を実装する

【Unity入門】簡単2Dゲームの作り方|初心者でも作れるジャンプアクション【全6回】

この記事は「初心者でも作れるUnity簡単2Dゲームの作り方講座」の第4回です。

前回は進む方向に合わせてプレイヤーの向きを変え、左右キーを押しているときだけ歩きアニメーションが再生されるようにしました。

また、Main Camera が Player の動きに合わせて横方向に追従するようにし、横スクロールゲームらしく画面が動くところまで作成しました。

前回の記事:

Unity簡単2Dゲームの作り方【第3回】キャラクターアニメーションとカメラ追従を実装する
この講座では、Unity初心者の方でも作れる「2D横スクロールアクションゲーム」を作成していきます。前回まででプレイヤーを左右に動かして地面にいるときだけジャンプできるようにしました。前回の記事:今回は Player が動いているように見せ...

今回はジャンプアクションで踏みつけるターゲットになる敵キャラクターを作成していきます。

まずは敵キャラをステージ上に配置し、左右に動くようにします。そのあと、敵を上から踏んだら倒せる処理を作成します。

左右に動く敵キャラクターを作ろう

まず敵の動きだけを作成してみましょう。

敵のオブジェクトを用意する

Project ウィンドウから Assets > 横スクロールアクションゲーム画像素材 を開き、その中にある「スライム」 Scene ビューにドラッグ & ドロップしましょう。

次に、Hierarchy から「スライム」を選択し、Inspector 上部の名前を「Enemy」に変更します。

 

Transform の Position以下のように設定しておきましょう。

これで敵キャラをステージ上に配置できました。

次に、Enemy に物理を適用します。
Player と同じように、Enemy にも Rigidbody2D を追加します。Inspector の Add Component から Physics 2D > Rigidbody2D を選択しましょう。

また、Player と同じように、Rigidbody2D の Constraints にある Freeze RotationZ にチェックを入れておきましょう。

これを設定しておくと、Enemy が地面やプレイヤーにぶつかったときに、勝手に回転しなくなります。

次に当たり判定を追加します。
Inspector の Add Component から Physics 2D > Capsule Collider 2D を選択しましょう。

これで敵キャラのUnityエディタ上での準備は完了です。

Unity C#スクリプトを書いて敵キャラの行動を作ろう

次に、敵を左右に動かすスクリプトを作成します。今回は指定した範囲をひたすら往復するだけのシンプルな敵を作成します。

Project ウィンドウから Assets 内の Scripts フォルダを開きます。Scripts フォルダの中で右クリックし、Create > MonoBehaviour Script を選択しましょう。作成したスクリプトの名前は「EnemyPatrol2D」にします。

作成したスクリプトをダブルクリックで開きましょう。開いたら、EnemyPatrol2D の中身を以下のように書き換えます。

EnemyPatrol2D

スクリプトの解説

Start で Enemy の最初の位置を保存しています。

この位置を基準にして、右にどこまで進むか、左にどこまで進むかを決めます。

例えば、moveDistance が3 のとき、Enemy は最初の位置から右に3マス、左に3マスの範囲で動きます。

次に、Enemy の SpriteRenderer を取得しています。

SpriteRenderer は、画像の表示を担当しているコンポーネントです。

今回は enemySprite.flipX を使って、Enemy の見た目を左右に反転させるために取得しています。

次はUpdate の中を見ていきましょう。

この 1 行で、Enemy を左右に動かしています。Translate は、オブジェクトの位置を今の場所から少しだけ移動させる処理です。今回のコードでは、右方向を表す Vector2.right に、進む向き、移動速度、時間をかけています。

それぞれの役割は以下の通りです。

Vector2.right 右方向
moveDirection 進む向きを決める
moveSpeed 移動速度を決める
Time.deltaTime フレームごとの動きの差を少なくする

Time.deltaTime とは?

ここで使っている Time.deltaTime は、「前のフレームから今のフレームまでにかかった時間」です。

Update は毎フレーム呼ばれますが、1 秒間に何回呼ばれるかは環境によって変わります。たとえば、動作が軽い環境では 1 秒間にたくさん Update が呼ばれます。逆に、動作が重い環境では Update が呼ばれる回数が少なくなります。

もし Time.deltaTime を使わずに移動させると、Update が多く呼ばれる環境では速く動き、Update が少ない環境では遅く動いてしまいます。

そこで Time.deltaTime をかけることで、「1 フレームごとにどれだけ動くか」ではなく、「1 秒間でどれだけ動くか」という考え方にできます。つまり、Time.deltaTime は、ゲームの動きを環境に左右されにくくするために使います。

動作環境 Update の回数 Time.deltaTime の目安
60 FPS 1 秒に 60 回 約 0.016
30 FPS 1 秒に 30 回 約 0.033

moveDirection は、Enemy が右に進むか、左に進むかを決めるための変数です。

moveDirection が 1 のときはに進みます。

moveDirection が -1 のときはに進みます。

つまり、moveDirection の値を 1 と -1 で切り替えることで、Enemy の進む向きを変えています。

次に、Enemy が右端まで進んだかを判定しています。

transform.position.x は、Enemy の現在の X 座標です。startPosition.x + moveDistance より右に進んだら、右端まで来たことになります。右端まで来たら、moveDirection を -1 にして、今度は左に進むようにします。同時に enemySprite.flipXtrue にして、Enemy の見た目も左向きに反転させています。

次の else if では、その逆を行っています。

Enemy が左端まで進んだら、moveDirection を 1 にして今度は右に進むようにします。

同時に enemySprite.flipXfalse にして、Enemy の見た目を右向きに戻しています。

この処理が毎フレーム繰り返されることで、Enemy が決められた範囲を左右に往復するようになります。

動作を確認しよう

スクリプトを書き終わったら、Ctrl + S で必ず保存して Unity に戻りましょう。

次に、Project ウィンドウから Scripts フォルダを開き、作成した EnemyPatrol2D を Hierarchy の Enemy にドラッグ & ドロップしてアタッチしましょう。

ここまでできたら、一度ゲームを再生して動きを確認します。

再生してみると地面の位置などによってはEnemy が地面の上からそのまま下に落ちてしまうかもしれません。その場合はEnemyの位置を修正しましょう。

Hierarchy から Enemy を選択し、Inspector の Transform から Position以下のように調整します。

また、最初の設定だと左右に動く範囲が少し狭く感じると思います。EnemyPatrol2D の Move Distance を 5 に変更しましょう。

設定できたら、もう一度ゲームを再生します。

Enemy が地面の上に乗ったまま、左右に往復していれば成功です。

スーパーマリオのように敵キャラを踏んだら倒せるようにしよう

ここからはEnemy を踏んだら倒せるようにしていきます。

大切なのは、Enemy に触れたらいつでも倒せるのではなく、Player が上から踏んだときだけ倒せるようにすることです。ではどのように判定するのか確かめていきましょう。

敵キャラを踏みつける処理をC#スクリプトで書こう

前章で作成した EnemyPatrol2D をダブルクリックで開きましょう。

開けたら、以下のように追記します。

EnemyPatrol2D

スクリプトの解説

今回追加した処理では、Enemy に Player が当たったときに、上から踏んだのかを確認しています。

まずは OnCollisionEnter2D から見ていきましょう。

OnCollisionEnter2D は、自分の Collider 2D に、別の Collider 2D がぶつかった瞬間に呼ばれる関数です。今回の場合、Enemy に Player がぶつかった瞬間に、この中の処理が実行されます。

ぶつかった相手の情報は、引数の collision に入っています。

この部分では、ぶつかった相手に Player という Tag が付いているかを確認しています。つまり、「ぶつかった相手が Player なら、次の処理へ進む」という意味です。

この判定を使うために後で Player に Player Tag を設定します。

次に、こちらの処理です。

ここでは、Player が Enemy を踏んだのかを確認しています。IsStompedByPlayer は、下で作成している自分用の関数です。この関数の結果が true なら「踏んだ」と判断し、false なら「踏んでいない」と判断します。

Destroy は、GameObject を削除する処理です。ここでは gameObject と書いているので、このスクリプトが付いている Enemy 自身を削除します。つまり、踏まれた Enemy を消すことで、Enemy を倒したように見せています。

OnCollisionEnter2D とは?

OnCollisionEnter2D は、Collider 2D 同士がぶつかった瞬間に呼ばれる関数です。

2D アクションゲームでは、Player と Enemy、Player と地面、Player と障害物などが触れたかどうかを調べるときによく使います。

似たような関数には、以下のようなものがあります。

OnCollisionEnter2D ぶつかった瞬間
OnCollisionStay2D ぶつかっている間
OnCollisionExit2D 離れた瞬間

今回は「Enemy に触れた瞬間だけ判定できればよい」ので、OnCollisionEnter2D を使っています。

次に、踏んだかどうかを判定している IsStompedByPlayer を見ていきましょう。

先頭に bool と書いてあるので、この関数は truefalse を返します。ここではtrue なら「踏んだ」、false なら「踏んでいない」という結果になります。また、GameObject player と書くことで、判定したい Player オブジェクトをこの関数の中で使えるようにしています。

ここでは、Player に付いている Rigidbody2D を取得しています。Rigidbody2D を取得している理由は、Player が上に移動しているのか、下に落ちているのかを調べるためです。

次に、踏んだ判定に使う条件を作っています。

これは、Player が Enemy より上にいるかを調べています。transform.position.y は、オブジェクトの縦方向の位置です。Player の Y 位置が、Enemy の Y 位置より stompHeight 分だけ高ければ、Player は Enemy の上にいると判断します。

stompHeight は、「どれくらい上にいれば踏んだとみなすか」を調整する値です。

ここではPlayer落下中かどうかを調べています。linearVelocity.y は、Player の縦方向の速度です。この値が 0 以下なら、Player は上昇しておらず、下に落ちている状態です。

この条件を入れている理由は、ジャンプで上に向かっている途中に Enemy に触れただけで倒せてしまうのを防ぐためです。

最後に、この 2 つの条件をまとめています。

&& は「両方の条件が true なら true」という意味です。つまり、

  • Player が Enemy より上にいる
  • Player が落下中である

この 2 つが両方そろったときだけ、Enemy を踏んだと判定します。どちらか片方でも条件を満たしていない場合は false になり、Enemy は倒れません。

動作を確認しよう

スクリプトを書き終わったら、Ctrl + S で必ず保存して Unity に戻りましょう。次に、忘れずに Player に Tag を設定します。今回のスクリプトでは、Enemy にぶつかった相手が Player かどうかを Tag で判定しています。

そのため、Player に Player Tag が設定されていないと、Enemy を踏んでも処理が実行されません。Hierarchy から Player を選択しましょう。

Inspector 上部にある Tag から Player を選択します。

ここまでできたら、ゲームを再生して確認してみましょう。

Player が Enemy を上から踏んだときだけ Enemy が消えれば成功です。ただし、今の状態では「倒した」というより、Enemy がその場で消えただけに見えます。

そこで、Enemy を踏んだときに Player が上に跳ねるようにして、倒した感触をわかりやすくしていきます。

倒したらバウンドするようにしよう

EnemyPatrol2D をダブルクリックで開きましょう。

開けたら、以下のように追記します。

EnemyPatrol2D

スクリプトの解説

まず、Player を上に跳ねさせる力として、playerBouncePower を用意しています。

public にしているので、Inspector から数値を調整できます。数値を大きくすると、Enemy を踏んだあとに Player が高く跳ねます。

次に、Enemy を踏んだと判定されたときの処理に、以下の 2 行を追加しています。

1 行目では、Player の Rigidbody2D を取得しています。

ここで使っている collision は、Enemy にぶつかった相手との接触情報です。今回の処理では、先にこのように確認しています。

つまり、この if 文の中に入っている時点で、collision.gameObject は Player Tag が付いたオブジェクトです。そのため、collision.gameObject.GetComponent<Rigidbody2D>() と書くことで、Player に付いている Rigidbody2D を取得できます。

次に、取得した Rigidbody2D の速度を変更しています。

linearVelocity は、Rigidbody2D の現在の速度です。

new Vector2 の中では、横方向の速度と縦方向の速度を指定しています。

今回のコードでは

と指定しています。

つまり、Enemy を踏んだ瞬間に、Player の縦方向の速度を上向きに変えているということです。これにより、Enemy を倒したあとに Player が少し跳ねるようになります。

動作を確認しよう

ここまでできたら、Ctrl + S で必ず保存して Unityに戻りましょう。Unityに戻ったら、ゲームを再生して動きを確認します。

プレイヤーが敵を踏んだ時に少し上に跳ねれば成功です。横から敵キャラに触れたときに Enemyオブジェクトが消えないことも確認しておきましょう。

プロジェクトファイルのダウンロード

今回の講座で作ったプロジェクトファイルのダウンロードリンクを用意しました。

プロジェクトファイルのダウンロードはこちら >>

まとめ

今回は敵キャラクターを作成し、プレイヤーが上から踏むと倒せるようにしました。

これで敵らしい動きはできましたが、敵にずっと横から当たっても敵を押し続けられましたよね。

これでは敵をジャンプで踏みつぶすことができても、敵から当たられたりジャンプを失敗したときに何のペナルティもありません。

そこで、次回は敵に横や下から触れたときにゲームオーバーになる処理を作成します。

さらに、落下したとき、危険な障害物に触れたときにもゲームオーバーになる仕組みを実装していきます。

次の記事:

Unity簡単2Dゲームの作り方【第5回】敵接触・落下・とげでゲームオーバーになる仕組みを実装する
この記事は「初心者でも作れるUnity簡単2Dゲームの作り方講座」の第5回です。前回は敵キャラクターのスライムを左右に動くようにして、プレイヤーが上から踏んだときだけ倒せるようにしました。さらに、敵を踏んだあとにプレイヤーが少し上へバウンド...

【ゲームの作り方講座もプレゼント中!】

現場レベルのゲーム制作が、すべてここで学べます。

【永久会員チケット】

永久会員チケット|Unity入門の森

全講座を見放題で学ぶ

ソースコード・素材・プロジェクトすべて公開。
Unityの基礎から応用まで、一生使えるスキルを体系的に習得。

コメント

タイトルとURLをコピーしました