【Unity初心者向け】作りながら覚えるゲーム制作講座 #5 弾と当たり判定

前回までで、キーボードで操作できる自機と地面を作成しました。
でも、まだゲームという感じではありませんね。

今回は落ちてくる弾を作って、それに当たると自機が消えるようにします。
弾を避けるという要素が入ると、一気にゲームらしさが出てきます!

/* 今回も先に完成形をご覧ください。 */

それでは始めていきます!

弾のオブジェクトを作成する

まずは弾のオブジェクトを作成します。
今回は 球体 (Sphere) を使用します。

Hierarchy の中を右クリックし、「3D Object」→「Sphere」を選択してください。

そして、名前を「Bullet」に変更し、位置を適当な高さにしてください。

弾のスクリプトを作成してアタッチする

第2回で自機に対して Player スクリプトを作成してアタッチしたのと同じように、今回は弾に対して Bullet というスクリプトを作成してアタッチします。

まず Project ウィンドウの中を右クリックし、「Create」→「C# Script」を選択してください。

次に名前を「Bullet」にして確定し、オブジェクトにドラッグ&ドロップしてください。

弾を落下させる

では、Bulletスクリプトに弾を落下(下に移動)させるプログラムを書いていきます!
自機を作った時、最初に自動的に右に移動させたのと基本的には同じです!

ただ、移動する方向は下に変えます。
下に移動させるには、 Y座標 をマイナス方向に移動させます。

今回も簡略化のために Start メソッドを消してあります。
そして y という変数を使って Y座標 を制御しています。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Bullet : MonoBehaviour
{
    float y = 12.0f;

    // Update is called once per frame
    void Update()
    {
        // 下に移動
        y -= 10.0f * Time.deltaTime;

        // 位置を更新
        transform.localPosition = new Vector3(0, y, 0);
    }
}

これで弾が落下するようになりました!

ちなみに、物体を落下させるには RigidBody というものを使って物理的に落下させる方法もあります。
ただ、今回は物理挙動は使わずに自分で落下させています。

弾が地面に着いたら位置をリセットする

弾が落ちてくるようになりましたが、今のままだと永遠に落下し続けてしまいます。
なので、地面に着いたら位置をリセットして再び上から落下するようにしてみましょう。

○○したら△△する」という処理には if文 を使用します。
第3回のキーボード入力判定でも使いましたね。
実際のイメージはこんな感じです。

if (/* 地面に着いたら */)
{
    /* 位置をリセット */
}

「地面に着いたら」という条件の書き方

地面に着いたら」というのは、「地面より下に行ったら」、すなわち「y がマイナスになったら」ということです。
つまり、変数と他の数値を比較する必要があります。

数値の比較

プログラムで数値同士を比較するには、「等号」と「不等号」というものを使用します。
等号は1種類、不等号には4種類あり、それぞれ次のような意味になります。

記号使用例意味
==a == ba と b が等しい場合
>a > ba が b よりも大きい場合
<a < ba が b よりも小さい場合
>=a >= ba が b 以上の場合
<=a <= ba が b 以下の場合

」のように半角に存在しない記号は、「>=」のように2つの記号を並べて書くのがポイントです。
また、等号の場合はイコールを2つ書くのもポイントです。
なぜなら、イコールが1つだと代入と一緒の書き方になってしまうからです。

今回は、「y が 0.0 よりも小さい場合」なので「<」を使用します。
実際に if 文の中に入れてみましょう。

if (y < 0.0f)
{
    /* 位置をリセット */
}

ちなみに、「地面に着いたら」というのは「y が 0.0 ジャストになったら」、つまり if (y == 0.0f) でも良いのではないかという疑問があるかもしれません。
しかし、変数の講座で float の計算には誤差があるという話を少しだけしたと思います。
また、毎フレーム移動する量も処理落ちなどによって微妙に変わることもあります。
つまり、実際には 0.09 → -0.01 のようになってしまい、確実に 0.0 ジャストになるとは限らないのです。

「位置をリセット」の処理の書き方

位置をリセットする」ということは、すなわち y を初期値に戻すということです。
つまり、 y に最初の値である 12.0 を代入します。

これも実際に if 文の中に入れてみましょう。
ついでに、処理の内容を忘れないようにコメントも書いておきます。

// 地面より下に行った場合
if (y < 0.0f)
{
    // 位置をリセット
    y = 12.0f;
}

自機と弾の当たり判定を行う

では、いよいよ自機と弾の当たり判定を行ってみましょう!
このゲームでは、弾に当たると自機が消えるようにしたいと思います!

当たり判定が検出されたときの処理を追加する

まず、 Player スクリプトの中に当たり判定が検出されたときの処理を追加します。
それには、 OnTriggerEnter というメソッドを使用します。

急に新しいメソッドが出てきましたが、心配しないでください!
Update メソッドが毎フレーム実行されるのと同じで、 OnTriggerEnter メソッドも当たり判定が検出されたときに実行されるという決まりを持ったメソッドです。

では、 OnTriggerEnter メソッドの書き方を見てみます。

private void OnTriggerEnter(Collider other)
{
    /* 当たったときの処理 */
}

今回は、当たった時の処理として「自機を消す」ということを行います。

自機を消す

自機を消すということは、Playerスクリプトにとって「自分自身のオブジェクトを消す」ということになります。

自分自身のオブジェクトを消すには Destroy(gameObject); と書きます。
実際に OnTriggerEnter メソッドの中に入れてみましょう。
ついでにコメントも書いておきます。

// 当たり判定が検出されたときに実行される
private void OnTriggerEnter(Collider other)
{
    // ゲームオーバー(自機を消す)
    Destroy(gameObject);
}

これで、当たり判定が検出されたときに自機を消す処理ができました!

ただ、これだけでは当たり判定の検出は行われません。
実際に当たり判定を検出させるには、オブジェクトに対しての設定も必要になります。

当たり判定が検出されるように設定を追加する

当たり判定を行うには、自機と弾の両方に設定が必要になります。

自機の設定

まず、当たり判定を行うには Rigidbody というコンポーネント(部品)が必要になります。
このゲームでは自機が当たり判定を行うメインのオブジェクトになるので、 Cube オブジェクトに対して Rigidbody を追加します。

Inspector の下にある「Add Component」ボタンをクリックし、検索欄に「rigid」と入力してください。
候補に出てくる「Rigidbody」をクリックして追加してください。

そして、 Inspector に追加された Rigidbody の中にある Is Kinematic というチェックボックスを ON にしてください。
これを ON にすると、そのオブジェクトの物理演算が行われなくなります。

当たり判定を行うために Rigidbody を追加すると、デフォルトで物理演算も行われるようになります。
ただ、今回は当たり判定だけが必要で物理演算は必要ありません。

弾の設定

次に、弾のほうの設定です。
まず Bullet の Inspector の中に、元から Box Collider というコンポーネント(部品)があることを確認してください。
確認できたら、そこにある Is Trigger というチェックボックスを ON にしてください。

これで、先ほどの OnTriggerEnter で当たり判定が検出できるようになります!

実行して確認する

では、動作を確認してみましょう。
ゲーム実行して、弾に当たってみてください。
当たった瞬間に自機が消えるはずです!

今のままだと弾の動きが同じパターンの繰り返しになってしまいますが、これは次回の講座でランダムな動きになるようにしたいと思います。

当たり判定のサイズを調整する

実際にプレイしてみると、弾に少し触れただけなのにゲームオーバーになってしまい違和感を感じてしまうかもしれません。
これは、デフォルトでは見た目上のサイズと当たり判定のサイズが完全に一致しているためです。

実際のゲーム(特にシューティングゲームなど)では、ダメージ判定などは見た目上のサイズよりも小さいことが多いです。
今回のゲームでも当たり判定を少し小さくしてみましょう。

Box Collider の Size を調整

それでは、自機の当たり判定を小さくします。
Cube の Inspector にある Box ColliderSize という項目を見てください。
デフォルトでは全て 1 になっています。

これを好きなサイズに変更してください。
ここでは 0.7 にしてみます。
これで、当たり判定のサイズが 0.7 倍になります!

実際にゲームを実行して、少しだけ弾に触れてみてください。
かすった程度ではゲームオーバーにならないことが確認できると思います!

まとめ

これで、弾を避けるというというゲーム性が生まれました!

ただ、弾の動きが毎回同じで変化がありませんね。
次回は弾の動きに変化をつけるため、発射位置と速さをランダムにしたい思います!
ランダムな要素を扱えるようになると、ゲームで表現できる内容が一気に増えます!