top of page

Unityで「シューティングゲーム」をつくろう!Vol.22

前回はPlayerの攻撃を作って、敵に当てるところまで完成しています。今回は敵のHPが0になったタイミングで爆発を発生させて、敵を消滅させるところまで。


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

 

これまで使ってきた爆発のエフェクトは、若干地味なので、派手なアクションを使いたいと思います。アセットストアにアクセスして取得します。


①今回選んだのは「True Explosions!」。ボリュームも多くないようなので、全てインポートしておきましょう。(一部だけ取得したら、エラーが発生してしましました。原因を追及するよりも全部取得したほうが効率がいいです)


②取得したアイテムから、[System] => [Prefabs] と進んでいただき、「Explosion2D」というプレハブを使います。

このまま使うと、大きすぎたり、また速すぎたりするので、若干修正しておきます。「Explosion2D」をダブルクリックして、編集モードに入ります。

この「Explosion2D」は3つの子要素で形成されているようです。まずはすべての子要素の「Renderer」を指定します。

ParticleSystemの 「Renderer」の指定方法は、前回学習しましたね。


③子要素3つを選択した状態で、Instagramの「ParticleSystem」コンポーネントを展開します。この「Renderer」というくくりのなかの「Sorting Layer ID」という値を「Player」に指定します。

これでは 「StationA」より手前に見えてくるはずです。

続いて子要素、1つずつ、パラメータを指定していきます。


④「ShockWave」 は衝撃波です。爆発の前に走る波ですね。

初期設定では、大きすぎるので「StartSize」を5に変更します。さらに動きが早すぎるので「Sumiration Speed」を0.8 に変更します。

⑤つづいて子要素の「FireBall」の値を変更します。これは爆発時に発生する火の玉、つまり爆発本体です。

初期設定では、やはり大きすぎるので「StartSize」を変更します。値を2つ指定できるようですが、左と右の間の乱数という意味の様です。今回は左に1を、右に2を入れて、1から2の間の乱数と指定します。

動きはやはり早すぎるので「Sumiration Speed」を0.5 に変更します。



⑥「BaseSmoke」は爆発後の煙です。これは「FireBall」と同じ値にしましょう。


これで素材の準備はOKです。ではプログラムを改造していきます。

前回作成したスクリプトファイル「EnemyStationAManager.cs」を立ち上げてください。

先に爆発のコルーチン型関数を作っていきます。


事前に 変数:explosion という名前で爆発プレハブ を指定しておきます。


StationA_Bomb() という名前のコルーチン型関数をでは以下の14個の処理を記述していきます。


❶前回作成した、動きを管理する Bool型変数:IsMove を false に指定します。

これで通常の動きを止めます。後で通常の動きを管理する関数「StationA_Move()」を一部修正します。


❷新たな動きは止まりますが、現在速度を持ってしまっているので、それを止める必要があります。そこで、今持っているvelocity を 0 にします。


❸StationA上のいろいろな場所で小爆発を発生させたいと思います。

foh文を使って、小爆発を生成するプログラムを20回繰り返します。


❹爆発の発生場所のx座標を決めています。StationAのポジションから左右に4の範囲から乱数で取得します。


❺は❹と同じで、y座標を指定しています。StationAは縦長なので、上下に8の範囲を指定しています。


❻は連鎖的に爆発が発生する演出です。繰り返し処理の中に0.1秒から0.3秒の乱数をとって、不規則な連鎖を表現します。


❼ここで爆発プレハブを生成します。❹と❺で指定した場所を使っています。


❽20回の繰り返しが終わったら、最後の大爆発を生成します。

今までのプレハブと違って、大きく、長く爆発を表現したいので、いったん生成したプレハブをゲームオブジェクトとして変数化しておきましょう。


❾生成のポジションはStationAの場所をします。


➓爆発の大きさ、速さを指定するには、プレハブの「ParticleSystem」の各パラメータを指定する必要があります。このコードでは、子要素の「FireBall」を探してきて、「ParticleSystem」コンポーネントを取得、それをvar型(推論型)の変数に代入します。

var型は推論型なので、同じコード内から型を推論できなければならないですね。今回は「ParticleSystem」型と推論できるので、使うことができました。


⓫ParticleSystem」の startSize を50に指定して、大爆発を作ります。


⓬同様に playbackSpeed を0.2f にすることで、爆発をゆっくり処理、つまり長く存続できるように指定します。


⓭StationAは爆発直後に消えると不自然なので、2秒待ちます。


⓮最後はDestroy関数で削除です。

 

[SerializeField] GameObject explosion; //爆発のプレハブ


IEnumerator StationA_Bomb()

{

IsMove = false; //❶通常の動きを止める

sARb2d.velocity = transform.up * 0; //❷速度を0にする

for (int i = 0; i < 20; i++) //❸小さな爆発を20回繰り返す

{

float x = transform.position.x + Random.Range(-4.0f, 4.0f); //❹爆発位置(x)

float y = transform.position.y + Random.Range(-8.0f, 8.0f); //❺爆発位置(y)

yield return new WaitForSeconds(Random.Range(0.1f, 0.3f)); //❻爆発間隔

Instantiate(explosion, new Vector3(x, y, 1), Quaternion.identity);//❼爆発生成

}

//最後の大爆発の処理

GameObject bomb = Instantiate(explosion); //❽大爆発を生成し変数にセット

bomb.transform.position = transform.position; //❾ポジション指定

//➓fireBall の子要素"FireBall"から「ParticleSystem」を取得し変数にセット

var fireBall = bomb.transform.Find("FireBall").GetComponent<ParticleSystem>();

fireBall.startSize = 50; //⓫大きさを指定

fireBall.playbackSpeed = 0.2f; //⓬スピードを指定

yield return new WaitForSeconds(2f); //⓭2秒待つ

Destroy(gameObject); //⓮削除

}

 

これで爆発演出ができました。

あとは既存のプログラムを修正して、このコルーチンを発動させましょう。

侵入判定 OnTriggerEnter2D() 関数の中で、"PlayerMissile"が侵入してきたら、hpを減らすというプログラムを前回作成しました。その中に追記します。

⓯もしhpが0になったら、StartCoroutine()関数で、上で作成した関数 StationA_Bomb() を発動しています。


⓰は修正です。前回やればよかったのですが、 while (true) を while (IsMove)  に修正します。これで、爆発が始まったら動きがストップします。

 

private void OnTriggerEnter2D(Collider2D collision)

{

if (collision.tag == "PlayerMissile")

{

hp--; //記述済み

Debug.Log("ボス:"+hp); //記述済み

if (hp == 0) //⓯もし hp が 0 になったら

{

StartCoroutine(StationA_Bomb()); //コルーチン StationA_Bomb() 発動

}

}

}


IEnumerator StationA_Move()

{

//記述済み

transform.position = new Vector3(Random.Range(-15f, 15f), 12f, 0);

sARb2d.velocity = new Vector2(0, -1f); //記述済み

yield return new WaitForSeconds(3); //記述済み

sARb2d.velocity = transform.up * 0;  //記述済み

yield return new WaitForSeconds(0.5f); //記述済み

IsMove = true; //記述済み

while (IsMove) //⓰

{

float x = Random.Range(-3.0f, 3.0f); //記述済み

float y = Random.Range(-3.0f, 3.0f); //記述済み

Vector2 direction = new Vector2(x, y); //記述済み

sARb2d.velocity = direction * speed; //記述済み

yield return new WaitForSeconds(3); //記述済み

sARb2d.velocity = transform.up * 0; //記述済み

yield return new WaitForSeconds(1); //記述済み

}

}

 

これで「StationA」の爆発演出は完成しました。

では起動させてみましょう。ちゃんと小爆発が発生し、最後は大爆発になると思います。爆発の速さ、大きさ、小爆発の回数や、間隔などは各自調整してみましょう。


ここで、一つ問題が発生しています。爆発のプレハブがいつまでも消えないようです。消す方法はいくつかありますが、今回は「Explosion2D」にプログラムを一つ追加して、消滅管理を行います。


「Explosion2D.cs」 というスクリプトファイルを生成して、以下のコードを記述します。

せっかく var型を覚えたので、忘れないうちにもう一回使ってみましょう。

Update関数の中で、Explosion2D の子要素である「BaseSmoke」を探してきて、そこから「ParticleSystem」を持ってきて、particle という変数に代入しています。

if文の中の条件式 !particle.IsAlive() は"particle" が起動していなければ、ということです。子要素の「BaseSmoke」の「ParticleSystem」は役割が終わったら止まります。つまり、「BaseSmoke」の動きが終了したら、という意味になりますね。 

 

void Update()

{

var child = transform.Find("BaseSmoke").gameObject;

var particle = child.GetComponent<ParticleSystem>();

if (!particle.IsAlive()) //もし"particle" が起動していなければ

{

Destroy(gameObject); //このゲームオブジェクトを削除

}

}

 

これを「Explosion2D」にアタッチして、再度起動させてみましょう。

今度はプレハブが順次消えていくのを確認することができたと思います。


はい、今回はここまで。

次回は、ここまでの敵の出現をいったん整理してみたいと思います。

 

教室では実際に通って頂いての授業の他、ちょっとしたお困りごとに対するオンライン授業やオンラインサポートも行っております。

お困りごとのある方、ご興味がある方は、ぜひお問い合わせください。


お問い合わせは こちら から。

体験授業のお申込みは こちら から。


過去の作品はこちらから。

Vol.20までの作品は、下のVol.21 文末のリンクからどうぞ

Unityで「シューティングゲーム」をつくろう!Vol.21