Unityで作る「シューティングゲーム」Vol.08

Unityで作る「シューティングゲーム」前回はデブリを作り、乱数で発生させるプログラムを作成しました。
今回はこのデブリに当たったら、また前々回作った隕石にぶつかったら、プレイヤーがダメージを受ける、という動きを作ってみます。

では早速作っていきましょう!

Step:1 デブリ、隕石の修正と確認

プレイヤーがデブリ、または隕石と衝突した際、何らかのイベントをさせるためには、互いに「Collider」というコンポーネントを持っている必要があります。
現在、隕石とデブリには「CircleCollider2D」「BoxCollider2D」というコンポーネントをつけていますね?
さらにこの「Collider」ですが、「衝突判定」と「侵入判定」をさせてあげることができます。
「衝突判定」は文字通り、2つ以上のオブジェクト同士が衝突する際に信号を出力、衝突後は互いの動きに影響を与えます。
一方「侵入判定」は互いは物理的な影響を受けることはなく、オブジェクトの指定した領域に侵入したときに信号を出力するものです。
Colliderコンポーネントの「IsTrigger」というパラメーターにチェックを入れることでこれが実現します。

では「Collider」をもったオブジェクトが複数あった時、特定の種類のオブジェクトのみに当たり判定をさせるにはどうすればよいでしょうか?

この実現には「Tag」というものを活用します。
説明が長くなりましたが、今回はこの「Tag」を使って衝突判定を行います。

①まずは「隕石」ですが、Inspector の確認を行います。

  1. Tagに「Asteroid」が設定されてある。
  2. 「CircleCollider」の「IsTrigger」のチェックが外れいている(=衝突判定)

この2点を確認します。

Unityで作る「シューティングゲーム」Vol.08

いん石のスクリプトファイルですが、出現するタイミングが若干遅いようです。
隕石が画面途中に突如出現するような動きになっていますね?
出現時のY座標を修正しておきましょう。
隕石の生成を管理しているのは「GameMangager」です。

❶「GameMangager.cs 」の 隕石生成の関数 void CriateAsteroid() の生成時のY座標の値を 20f に変更します。

void CriateAsteroid() //隕石生成
{
    GameObject asteroid = Instantiate(asteroidPrefab);
    asteroid.transform.position = new Vector3(Random.Range(-20, 20), 20f, 0);  //❶
}

さらに隕石のプレイヤーと衝突したときに爆発するように修正します。
まずは「 Asteroid.cs」に以下のコードを追加しましょう。
この関数は、プレイヤーが隕石と衝突した際に、プレイヤー側から呼び出したいと思います。
ということで、関数のアクセス修飾子には「public」を指定しておきます。

public void DestroyAsteroid()  //隕石の爆発関数
{
    Destroy(gameObject);       //消滅 
    Instantiate(explosion, transform.position, Quaternion.identity); //爆発の生成
}

続いてデブリですが、現在Tagが デフォルト値 になっています。

②Tagに「Enemy」をセットします。
作っていない場合は新たに作成しセットしましょう。
こちらは侵入判定で検知したいと思います。
「BoxCollider」の「IsTrigger」にチェックが入っているのを確認しましょう。

Unityで作る「シューティングゲーム」Vol.08

デブリのプログラムですが、出現場所は問題ないのですが、クローンによっては途中で消滅してしまうようです。
消えるまでの時間を調整します。

❷ 現状、Start()関数 に、Destroy(gameObject,3f); 生成後3秒後に削除、というコードを記述していますが、これを削除します。

❸ さらに Update()関数 に、Y座標が-15 を下回ったら削除、というコードを追加します。

Debris.cs」 を開いて、以下のコードを追加、修正します。

void Start()
{
    debRenderer = GetComponent<SpriteRenderer>(); //記述済み
    debRenderer.sprite = sprites[Random.Range(0, 6)]; //記述済み 
    GetComponent<Rigidbody2D>().velocity = new Vector2(Random.Range(-15, 15), Random.Range(-10, -2)); //記述済み
    Destroy(gameObject,3f); //❷削除 
}

void Update() 
{
    if (transform.position.y < -15f) 
    {
        Destroy(gameObject); //❸Y座標が-15を下回ったら削除 
    }
}

これで隕石とデブリの修正は完了です。

Step:2 プレイヤーのHP管理

「PlayerCotroller.cs」 スクリプトファイルを改造します。
内容はちょっと下にあります。

❹ まずはPlayerの爆発演出を行いますので、爆発のプレハブを持たせる準備をします。
 [SerializeField] GameObject Explosion; を記述

❺ プレイヤーに変数「HP」を持たせ、❽で初期値を10に指定します。

❻ void Destroy()関数ではPlayer自身の爆発と消滅を指定しています。
 都度爆発と消滅を記述してもいいのですが、複数個所で使用する場合は、関数にしてしまった方が楽ですね。  

❼ Instantiate(Explosion, transform.position, Quaternion.identity);
 Instantiate(第一引数:何を,第二引数:どこに,第三引数:向き);
 Instantiate() 関数では第一引数に指定したオブジェクトを生成します。
 今回は爆発のプレハブを指定しています。
 同じエフェクトを使いまわしていますが、別のものを使ってもいいでしょう。
 各自好きなエフェクトをアセットストアから取得して指定してみてください。
 第二引数の生成場所には自分の場所を指定しています。
 第三引数の Quaternion.identity は「回転しない」という意味でしたね?

❾ void OnTriggerEnter2D(Collider2D collision) は侵入判定です。
 カッコの中は引数で、Collider2D型 の変数 collision には衝突した対象が渡されます。

➓ if(collision.tag == “Enemy”)
 if の中の collision には侵入した対象が入ります。
 ”==” は比較演算子で「同じ」という意味を持ちます。
 ちなみに”=” イコールが一つだけだと、「代入」という意味になりますよね?
 合わせると、侵入した対象が持っている Tag が”Enemy”ならという意味になります。

⓫ hp–;”–” はデクリメント といいます。hp=hp-1 と同じ意味です。
 侵入するたびにhpを1ずつ減らす、という意味になります。

⓬ if (hp <= 0) Destroy(); もしhpが0以下になったら、作成済みのDestroy()関数を呼び出す、という意味です。

⓭ void OnCollisionEnter2D(Collision2D collision) は衝突判定です。
 先に説明したOnTriggerEnter2Dと基本の部分は同じになります。

⓮ if (collision.gameObject.tag == “Asteroid”)
 衝突した対象のゲームオブジェクトのタグが”Asteroid”なら、という意味です。
 今回はTrigger でなく、オブジェクトなので、gameObject.と指定する必要があります。
 先ほどと若干違いますので気を付けてください。

⓯ hp-=2;
 hp = hp – 2 という意味になります。
 わかりにくいかもしれませんが、hp という文字を1回しか書かなくても良いので楽です。

⓰ collision.gameObject.GetComponent<Asteroid>().DestroyAsteroid();  
 「PlayerController」というクラスから、別のクラス「Asteroid」の関数を起動させています。
 別クラスを参照する方法はいくつかありますが、まずはそのクラスを探し出すこと。
 今回は衝突したゲームオブジェクトが持っているスクリプトファイルが、そのクラスだったので見つけることができました。
 衝突した対象から GetComponent<Asteroid>() でスクリプトファイルを取得、その中の DestroyAsteroid()関数 を呼び出しました。

[SerializeField] GameObject Explosion; //❹爆発エフェクト
public int hp;                         //❺Player のHP

void Destroy()       //❻消滅させる関数を作成
{
    Instantiate(Explosion, transform.position, Quaternion.identity); //❼爆発生成
    Destroy(gameObject);                                             //消滅
}

void Start()
{
    shot_speed = 800;                           //記述済み
    playerRb2d = GetComponent<Rigidbody2D>();   //記述済み 
    transform.position = new Vector3(0, -5, 0); //記述済み
    hp = 10;                                    //❽HPの初期値を10に指定
}

void OnTriggerEnter2D(Collider2D collision)     //❾侵入判定
{
    if(collision.tag== "Enemy")                 //➓対象のタグが"Enemy"なら
    {
        hp--;                                   //⓫hpを1ずつ減らす 
        if (hp <= 0)                            //⓬hpが0以下のとき
            Destroy();                          //Destroy()関数発動
    }
}
void OnCollisionEnter2D(Collision2D collision)  //⓭衝突判定
{
    if (collision.gameObject.tag == "Asteroid") //⓮対象のタグが"Asteroid"なら
    {
        hp-=2;                                  //⓯hpを2ずつ減らす 
        collision.gameObject.GetComponent<Asteroid>().DestroyAsteroid(); //⓰DestroyAsteroid()を発動 
        if (hp <= 0)                            //hpが0以下のとき
            Destroy();                          //Destroy()関数発動
    }
}

最後の部分、ちょっと難しいですよね?
説明が長くなりましたが、これでスクリプト部分は完成です。

③ 最後はプレイヤーのインスペクターから、PlayerControllerの「Explosion」にExplosionプレハブを指定してあげましょう。

Unityで作る「シューティングゲーム」Vol.08

これで動かしてみてください。
大量のデブリがプレイヤーのマシンに衝突、10回当たるとプレイヤーは消滅すると思います。
hp が減少していくのがわかりにくいという場合は、hp が変化するタイミングで debug()関数 を発動させるのもいいかもしれませんね?
hp–; //この後にDebug.Log(hp);
これでコンソールにhpの値が表示されると思います。

教室では実際に通って頂いての授業の他、Unityのオンライン授業やオンラインサポートも行っております。お困りごとのある方、ご興味がある方は、ぜひお問い合わせください。
お問い合わせは こちら から。
体験授業のお申込みは こちら から。

無料体験授業 いつでも受け付けています!

体験授業を受ける子供

スクラッチ、Unityでちょっとしたゲームを作ってみる

HTMLやCSSでWebサイト作成体験

初めてパソコンやタブレットに触れてみる

エクセルやワード、パワーポイントの学習をちょっと体験

まずは1時間程度の無料体験授業を受けて、教室の雰囲気や講師の人柄に触れて頂き、ご自身、お子様に合うのかどうかご確認ください!