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

前回はスプライトのリストを作成して、複数のアイテムを出現させる効果を実現しました。


今回は2つ目のアイテムとして攻撃の強化を実現させてみます。

現状、スペースキーで1発の弾、Zキーを押すと2発の弾が発射されます。

それを1つにまとめ、通常1発、強化アイテムを取得したタイミング2発撃、3発と攻撃が強化される、といった演出を作ってみます。

今回行うことは次の2つ

1,PlayerController を改造

2,PlayerBuret を改造

3,PlayerTurret を改造 


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

1、PlayerController の改造


Playerは「アイテムB」を取得した際、通常の単発攻撃から2発の攻撃に変更、さらにその状態で再度「アイテムB」を取得したら3発、さらに6発と4段階で攻撃が強化。逆に攻撃が強化された状態でダメージを受けると、1段階ずつ攻撃力が下がっていく。

フローにすると以下のような感じです。

変数「ShotPower」を作っておき、初期値を1,武器強化アイテムを取得するたびに変数の値を1づつ増やします。

「ShotPower」 が大きいほど強力な攻撃ができるようになるように改造します。

逆にダメージを受けたときに、変数「ShotPower」を1ずつ減らし、攻撃力を下げていきます。

変数「ShotPower」は最大でも4、最小でも1になるようにしておく必要がありますね。


その前に「ShotPower」が3,4 のとき、レーザー同士がぶつかってしまう恐れがあります。

Tagを指定してプログラム側から修正してもいいのですが、今回はUnityエディタ側で修正します。


①Player の Layer に「Player」Layer(作成済み)をセットします。


②この時、子要素(turret)にもLayerを反映させるか聞いてきます。

「Yes change children」を選択します。


③プレイヤーのレーザーのプレハブ(PlayerBulletPrefab)にはすでに「Player」Layerがついていると思います。

一応確認して、ついていなかったら付けておきましょう。

④Project Settings の「Physics 2D」から一番下の「Layer Collision Matrix」を表示させます。

ここはレイヤー同士の当たり判定を有効にするか無効にするか指定する場所です。

Layer「Player」同士が重なるポイントのチェックを外し、Pleyer同士の当たり判定を無効にしておきましょう。

では「PlayerController.cs」を立ち上げて、以下のコードを追加します。


❶まずは変数「shotPower」を宣言、初期値に1を代入しておきます。


❷「ItemB」を取得したときの動きを若干改造します。

まずはインクリメント「shotPower++;」で、ItemBを取得するたびに、変数「shotPower」を1ずつ増やします。

 しかし前述した通り 変数「shotPower」は1から4の間を増減しなければなりません。

 取得した際に4より大きくなったら、つまり5になったら強制的に4に置き換えます。


❸また、変数「shotPower」はダメージを受けた際に、1ずつ減らしていきます。

今度はデクリメント「shotPower--;」で1ずつ減少させます。

また❷と同様に1より小さくなってはいけませんので、1より小さくなったら強制的に1に置き換えます。


Shot()関数を若干修正します。

これまではPlayerが、レーザーに力を与えていました。

このままだとレーザーを複数作るとき、作業量が多くなるので、Playerはレーザー(プレハブ)を作るだけ、レーザーを動かすのは、レーザプレハブ本体にさせましょう。

この後、レーザープレハブのプログラム(PlayerBuret.cs)を、レーザーが前向きに飛ぶように改造します。


❹変数「shotPower」が1のとき、つまり通常攻撃のとき、レーザープレハブを1つだけ生成します。

Instantiate(weapon_prefab, transform.position, Quaternion.Euler(0, 0, 0));

その際、向きを Quaternion.Euler(0, 0, 0) つまり素材の向きに指定しています。


❺続いて変数「shotPower」が3のとき、つまりPlayerの先頭からレーザーが3発発射される動きを作成します。

ほぼ❹と同じですが、


Instantiate(weapon_prefab, transform.position, Quaternion.Euler(0,0,20));
Instantiate(weapon_prefab, transform.position, Quaternion.Euler(0,0,0));
Instantiate(weapon_prefab, transform.position, Quaternion.Euler(0,0,-20));

とZ軸を中心として、素材の向き、時計回りに20度回転、逆時計回りに20度回転、合計3つのプレハブを生成します。


public int shotPower=1;  //❶変数shotPowerを宣言

void OnTriggerEnter2D(Collider2D collision) //記述済み
{
if (collision.tag == "Item")	//記述済み
{
string name = collision.GetComponent<SpriteRenderer>().sprite.name;
	switch (name) //記述済み
	{
		case "ItemA":                	//記述済み
			SubHP(-1);		//記述済み
			break;			//記述済み
		case "ItemB":			//❷
			shotPower++;		//ShotPowerを加算
			if (shotPower > 4) 	//4より大きくなったら
				shotPower = 4;  //4 にする
			break;
		//以下省略
	}
}}

void SubHP(int h)
{
	hp -= h;	//記述済み
	HPText.text = "HP:" + hp.ToString();	//記述済み
	audioSource.PlayOneShot(playerSounds[2]);//記述済み
	if (hp <= 0)	//記述済み
	{
		StartCoroutine( Destroy());	//記述済み
	}
        else				//❸hpが残っていたら
        {
		shotPower--;		//shotPowerをデクリメント
        	if (shotPower < 1)	//1より小さくなったら
			shotPower = 1;	//1に置き換える
        }
}

void Shot()
{
if (Input.GetKeyDown(KeyCode.Space) && shotPower == 1) //❹通常攻撃
{
Instantiate(weapon_prefab, transform.position, Quaternion.Euler(0, 0, 0));
//bullet.GetComponent<Rigidbody2D>().AddForce(bullet.transform.up * shot_speed);//削除
audioSource.PlayOneShot(playerSounds[0]);	//記述済み
}

if (Input.GetKeyDown(KeyCode.Space) && shotPower == 3) //❺ShotPower3のとき
{
Instantiate(weapon_prefab, transform.position, Quaternion.Euler(0,0,20));
Instantiate(weapon_prefab, transform.position, Quaternion.Euler(0,0,0));
Instantiate(weapon_prefab, transform.position, Quaternion.Euler(0,0,-20));
audioSource.PlayOneShot(playerSounds[0]);	
}
if (Input.GetKeyDown(KeyCode.X)&&missilePreparTime>missileTime)
{
	//内部記述済み(省略)
}
missilePreparTime += Time.deltaTime;
}

PlayerControllerはこれで完成です。


2、PlayerBullet の改造


では続いて「PlayerBullet.cs」を改造します。

1,でPlayerは弾を生成するだけに変更しました。

従って弾(PlayerBulletPrefab)自体が生成されたタイミングで速度を持つ必要があります。


❻レーザーの速度を管理する変数「shot_speed」を宣言


❼変数「shot_speed」にについていた


❽Rigidbody2Dコンポーネントを取得して、AddForce()関数で前向きに、shot_speedの力を与えています。


この❻~❽は今までPlayerControllerについていた動き、そのままになります。


❾今回の準備段階で、レイヤー「Player」が付いたもの同士の衝突を無効にしました。従って今までついていた条件文が必要なくなりました。

if (col.tag != "Player" )

この一文とかっこを削除します。

float shot_speed;	//❻変数宣言(レーザーの速さ)
void Start()
{
	shot_speed = 800;	//❼速さを指定
	GetComponent<Rigidbody2D>().AddForce(transform.up * shot_speed);//❽速さを伝える
	transform.localScale = new Vector3(5, 5, 1);//記述済み
	Instantiate(shoot_effect, transform.position, Quaternion.identity); //記述済み
	Destroy(gameObject, 3f);//記述済み
}

void OnTriggerEnter2D(Collider2D col) //❾侵入判定条件を解除
{
//if (col.tag != "Player" ) //削除
//{
	Instantiate(hit_effect, transform.position, Quaternion.identity);
	Destroy(gameObject);
//}
}

PlayerBullet.cs の改造はここまでです。


3、PlayerTurretController の改造


最後はPlayer の両翼についたturretです。

ここからレーザーを発射させることで、2倍の攻撃を実現していましたね。

今まではZキーを押すことでレーザーが発射されましたが、PlayerControllerと同様、スペースキーで発射されます。

PlayerController が持つ変数「shotPower」の値を判定し、攻撃を行いますので、PlayerControllerにアクセスする必要がありますね。


❿PlayerController を使うための変数を宣言します。


⓫ここでは❿で宣言した変数に、PlayerControllerを代入します。

まずは GameObject.Find()関数を使って、Player を探し、そこからGetComponent()関数を使って、PlayerControllerを取得しています。

2段階で探している、というところがポイント。


⓬「shotPower」が2のときの攻撃、これは今までのZキーを押したときの攻撃と同じ動きです。

PlayerController同様、プレハブを生成するだけのプログラムに変更しました。


⓭「shotPower」が4のときの攻撃です。3方向に発射されるので、向きを変えたプレハブを3つ生成しています。


PlayerController playercontroller;  //❿PlayerCOntroller を格納する変数

void Start()
{
	playercontroller =