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

前回までで、EnemyStationAの動きができました。これでEnemy1,Enemy2,EnemyStationA の準備ができましたので、ルールを決めて出現させることができます。

ということで今回行うのは次の2つ。

1,敵をルールに従って登場させる

2,ここまでのバグや修正点の改修

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

まずは、今回修正した後の完成動画をYoutubeにアップしていますので、そちらをご確認ください。





 

1,敵出現のルール作成

現状、以下のルールで出現しています。

①Enemy1が左右から1対ずつ出現×3列 合計6体

②Enemy1が倒されるタイミングで、Enemy2を生成 合計6体

①② を無限ループ


今回作るルールは①②を2セット、その後EnemyStationAを出現させる、という簡単なもの。

「①②セット」の回数を数える必要がありそうですね。


「GameManager.cs」を立ち上げて、以下のように改造しましょう。

まず変数を2つ宣言しています。


❶この後生成するEnemyStationAのプレハブを変数で宣言


❷Enemyの出現パターンを管理する整数型の 変数:[ enemyAppPattern ]を宣言

「enemyAppPattern」 が 1,2 のときは「Enemy1」を出現させます。

「enemyAppPattern」 が 3 のときは、「EnemyStationA」を出現させます。


❸Start 関数の中で、❷で宣言した「enemyAppPattern」を初期化、1に指定します。


❹Update 関数の中で、「Enemy1」の出現条件に  enemyAppPattern<=2 つまり1 か 2 という条件を追加。


❺「EnemyStationA」の出現条件を指定。「enemyCount 」が 0、かつ「enemyAppPattern」が 3 のときです。


❻「EnemyStationA」を生成。


❼「enemyAppPattern」を1加算し、4にします。


❽コルーチン CreateEnemy() の最後に「enemyAppPattern」を1ずつ加算、1を2に、2を3にします。

 

[SerializeField] GameObject EnemyStationA; //❶EnemyStationAプレハブ

int enemyAppPattern; //❷Enemyの出現パターン管理変数


void Start()

{

scoreText.text = "Score:"+score.ToString();//記述済み

enemyAppPattern = 1; //❸初期化

}


void Update()

{

if (enemyCount == 0 && enemyAppPattern<=2) //❹Enemy1出現条件

{

StartCoroutine(CreateEnemy()); //記述済み

}

else if (enemyCount == 0 && enemyAppPattern == 3) //❺EnemyStation出現条件

{

Instantiate(EnemyStationA); //❻EnemyStationAを生成          

enemyAppPattern++; //❼出現パターン管理変数加算

}

D = Random.Range(0, 2000); //以下記述済み

if (D == 0)

{

CriateAsteroid();

}

else if (D <= 8)

{

CriateDebris();

}

}

IEnumerator CreateEnemy()

{

enemyCount = 6;

yield return new WaitForSeconds(2);

Enemy1Controller e1 = Instantiate(Enemy1).GetComponent<Enemy1Controller>();

e1.appPos = 1;

Enemy1Controller e2 = Instantiate(Enemy1).GetComponent<Enemy1Controller>();

e2.appPos = -1;

yield return new WaitForSeconds(2.2f);

Enemy1Controller e3 = Instantiate(Enemy1).GetComponent<Enemy1Controller>();

e3.appPos = 1;

Enemy1Controller e4 = Instantiate(Enemy1).GetComponent<Enemy1Controller>();

e4.appPos = -1;

yield return new WaitForSeconds(2.2f);

Enemy1Controller e5 = Instantiate(Enemy1).GetComponent<Enemy1Controller>();

e5.appPos = 1;

Enemy1Controller e6 = Instantiate(Enemy1).GetComponent<Enemy1Controller>();

e6.appPos = -1;

enemyAppPattern++; //❽出現パターン管理変数を加算

}

 

これで「GameManager.cs」の改造は完了です。

 

2,EnemyStationA の改修

続いて「EnemyStation」の改造を行っていきます。現在のプログラムでは移動制限が掛かっていますが、登場時にも移動制限が発生し、いきなり画面上に出現するようになってしまうので、それを修正。

さらに、上で作成した「enemyAppPattern」、さらに出現した敵がすべて倒されたかを管理する「enemyCount」を管理していくコードを追加します。

では「EnemyStationAManager.cs」を立ち上げて、以下のように改造します。


❾「EnemyStationAManager」クラスでは「GameManager」クラスを扱います。そのために GameManagerクラス型 の 変数:[gameManager] を宣言。GameObject のGameManager じゃないので、間違わないように。ここ、ややこしいですね?


➓Start関数の中で、❾で宣言した 変数:[gameManager] に値を代入します。Find()関数 はヒエラルキー上のオブジェクトを探す関数でしたね?探した「GameManager」(オブジェクト)からGetComponent関数 で「GameManager」(クラス)を取得しています。


番号はふっていませんが、HPは適当な数字に修正しておいてください。


⓫➓で値が入った変数:[gameManager] を使って、変数:[ enemyCount ] に1を代入、1対生存している、ということにします。


⓬ここでは⓫で1を代入して生存していることにした変数:[ enemyCount ] に、0 を代入して生存していないことにします。爆発演出のコルーチン StationA_Bomb() の最後にコードを追記。


⓭Update関数では、現状移動制限の実管理しています。登場時にこれを発動していしまうと、いきなり画面上に移動してきてしまします。

以前作った変数:[ IsMove ] True のときだけ、この動きを有効にします。ここではIF文を使って実現しています。

 

GameManager gameManager; //❾GameManagerクラスを呼出すための変数宣言


void Start()

{

speed = 2f; //記述済み

sARb2d = GetComponent<Rigidbody2D>(); //記述済み

StartCoroutine(StationA_Move()); //記述済み

hp = 20; //自由に変更

gameManager = GameObject.Find("GameManager").GetComponent<GameManager>(); //➓❾を検索

gameManager.enemyCount = 1; //⓫初期化

}


IEnumerator StationA_Bomb()

{

・・・

省略

・・・

Destroy(gameObject);

gameManager.enemyCount = 0; //⓬0に戻して敵がいなくなったことを宣言

}


void Update()

{

if(IsMove) //⓭登場時は移動制限がかからないように

{

transform.position = new Vector3(Mathf.Clamp(transform.position.x, -18f, 18f),

Mathf.Clamp(transform.position.y, -12f, 12f), 1); //記述済み

}

}

 

ここで1つ見た目の修正です。


①このまま動かすと、「EnemyStationA」と3つの「Turret」の間に、レイヤーの幅があり、小惑星が入り込んできていしまうようです。とても不自然なので下の図のように、Sorting Layer を1つ作り、Turret に指定します。


最後は、EnemyStationA を[03_Prefab]フォルダにドラッグ&ドロップしてプレハブ化、Hierarchy上のオブジェクトは削除しておきましょう。


ということで、「EnemyStationA」の改造は、いったん完成しました。


②ここで、1で改造した「GameManager」の変数「EnemyStationA」にこのプレハブをセットします。



 

3,その他の改造


まずはEnemy2の弾が出てくる間隔が早いのでちょっとだけ遅くします。

スクリプトファイル「Enemy2Controller.cs」を立ち上げて、コルーチン型関数 Shot() を一部改造します。

⓮ shotDelay の乱数の大きさを若干大きくします。ここはそれぞれ好きな値にしましょう。

 

IEnumerator Shot()

{

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

while (true) //記述済み

{

shotDelay = Random.Range(1.0f, 3f); //⓮発射の間隔を1~3秒の間の乱数に

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

GameObject Laser = Instantiate(EnemyBullet, transform.position, transform.rotation); //記述済み

Laser.GetComponent<Rigidbody2D>().AddForce(EnemyBullet.transform.up * shot_speed); //記述済み

}

}

 

続いて自分の弾、敵の弾、若干見にくいのでちょっと濃くしてみましょう。

スクリプトファイル「PlayerBullet.cs」を立ち上げて以下のコードを修正。


⓯元の素材を変更する方法もありますが、生まれてくるときのScale を指定します。

すでに記述してある数字を new Vector3(5, 5, 1) に変更します。

 

void Start()

{

transform.localScale = new Vector3(5, 5, 1); //⓯5倍に変更

Instantiate(shoot_effect, transform.position, Quaternion.identity); //Spawn muzzle flash //記述済み

Destroy(gameObject, 3f); //記述済み

}

 

敵の攻撃も同じように変更しておきます。


スクリプトファイル「EnemyBullet.cs」を立ち上げて上と同じように変更。

 

void Start()

{

transform.localScale = new Vector3(5, 5, 1); //⓰5倍に変更

Instantiate(shoot_effect, transform.position, Quaternion.identity);

Destroy(gameObject, 3f);

}

 

これで完成。

今回はここまで。

次回は、音を入れて以降かなと、思います。

 

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

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


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

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


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

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

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

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

最新記事

すべて表示

ファイブボックス 上田教室