Unityで簡単なシューティングゲームを作る[8]
Step8:ゲームオーバーの設定
始まりがあれば終わりあり…と言う訳でゲームオーバーの設定を行う。
※このサイトのチュートリアルはとりあえず自力でゲームを作ってみることを目的としているため、プログラム言語に関する解説部分はかなり大雑把で意訳気味です。プログラム言語(C#)について正しく、詳しく学びたい方は、入門書やUnityの解説サイトなどをご参考にしていただけたらと思います。また、このサイトはコピープロテクトをかけているため、画面上からスクリプトのコピペができません。「スクリプトはこちら」というリンクからテキストファイルを表示して使ってください。面倒くさくてすみません。
ルールと仕様を考える
はじめに、どうなったらゲームオーバーになるかルールを決める。今回はごくシンプルに敵を撃ち損なってしまったらゲームオーバーという形にする。そして次に仕様を考える。ゲームオーバーの処理としては「Game Over」と表示し、弾が打てなくなる、スコアが更新しなくなるなどが考えられるが、今回はごくシンプルに「Game Over」表示し、プレイヤーをステージから消すという処理を行う。プレイヤーをステージから消してしまえば弾を打つこともできないし、スコアが更新されることもないからだ。
パネルを作成する
まず、ゲームオーバーの画面を作成する。今ある画面の上に重ねる形でGame Overのテキストやリトライボタンを表示したいのでパネルを作成する。
ヒエラルキーリストの「Canvas」を選択した状態で、「+」ボタンをクリックし「UI」から「Panel」を作成。
ヒエラルキーリストの「Cancas」の「Score」の下にパネルが作成されるので、名前を「GOPanel」と変更する。「GOPanel」のインスペクタでは背景色の指定もできる。今回はゲームオーバー感がでるよう、半透明の赤色に設定。
ゲームビューに切り替えると、ステージとプレイヤーの上に半透明の赤い色がかぶさっているのがわかる。
Game Overのテキストを作成
作成したパネルの中にゲームオーバーのテキストを配置する。シーンビューに戻りヒエラルキービューの「GOpanel」を選択した状態で「+」をクリックし「UI」から「Text」を作成。
「GOPanel」の下に「Text」が作成されるので名前を「GameOver」と変更。「GOPanel」のインスペクタを以下のように設定する。ゲームビューに切り替えバランスを見ながら設定するとよい。
Rotation:X:0,Y:0,Z:0
Text:GAME OVER
Font Style:Bold
Font Size:25
Alignment:中央中揃え
Color:白
パネル切り替えのスクリプトを作成
ゲームオーバーのパネルができたらそのパネルの表示・非表示を切り替えるスクリプトを作成する。「Asetts」から「Create」でC#を作成し、ファイル名を「PanelManager」とする。
ファイルを作成したら以下のスクリプトを記述する。スクリプトはこちらから。
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; public class PanelManager : MonoBehaviour { [SerializeField] GameObject GOPanel; public void Start() { Playgame(); } public void Stopgame(){ GOPanel.SetActive(true); } public void Playgame(){ GOPanel.SetActive(false); } }
今回もユーザインタフェースに関わるスクリプトなのでusing UnityEngine.UI;を記述しておく。[SerializeField] は変数をUnityエディターから変数の値を格納したい時に使用する。
[SerializeField] GameObject GOPanel;
そして指定したオブジェクト「GOPanel」をパネルを表示する(=ゲームオーバー)Stopgame、パネルを非表示にするPlaygameという二つの関数を作る。
// パネルを表示する public void Stopgame(){ GOPanel.SetActive(true); } // パネルを非表示 public void Playgame(){ GOPanel.SetActive(false); }
そしてスタート時にはパネルを非表示にするPlaygameを命令させる。
// スタート時にパネルを非表示 public void Start() { Playgame(); }
スクリプトをアタッチする
スクリプトができたらオブジェクトにアタッチする。まずはアタッチするための空のオブジェクトを作成し名前を「PanelScript」とする。
作成したオブジェクト「PanelScript」に「PanelManager」をアタッチする。
関連づけを行う
スクリプトをアタッチした「PanelScript」のインスペクタを確認すると「PanelManager」の項目ができている。ここの「GOPanel」の欄が「No Object」となっているので、ここにヒエラルキーリストの「GOPanel」をドラッグ&ドロップして、関連づけをする。
関連づけがされると以下のように「GOPanel」と表示される。
この状態でゲームビューに切り替えてみると、先ほどのようにゲームオーバーの表示がされていない。「PanelManager」の中にあるスタート時はパネルを非表示にするという命令がきいているためである。
ゲームオーバーの処理を記述する
ゲームオーバーの画面ができたところで、今度はゲームオーバーの処理を記述する。まずゲームオーバー時にはプレイヤーを消したいので、プレイヤーを制御している「PlayerController」を開き、赤字の部分を追記する。スクリプトはこちらから。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerController : MonoBehaviour{
public GameObject bulletPrefab;
void Update () {
transform.localPosition = Range.ClampPosition( transform.localPosition );
if (Input.GetKey (KeyCode.LeftArrow)) {
transform.Translate (-0.1f, 0, 0);
}
if (Input.GetKey (KeyCode.RightArrow)) {
transform.Translate ( 0.1f, 0, 0);
}
if (Input.GetKey (KeyCode.UpArrow)) {
transform.Translate ( 0,0.1f, 0);
}
if (Input.GetKey (KeyCode.DownArrow)) {
transform.Translate ( 0,-0.1f, 0);
}
if (Input.GetKeyDown (KeyCode.Space)) {
Instantiate (bulletPrefab, transform.position, Quaternion.identity);
}
}
public void Deleteplayer (){
Destroy (gameObject);
}
}
画面からプレイヤーを削除するDeleteplayerという関数を作成し、これをゲームオーバーの時に呼び出すようにする。続いてゲームのルールを記載している「GameSystem」を開き、赤字の部分を追記する。スクリプトはこちらから。
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; public class GameSystem : MonoBehaviour { int score = 0; GameObject scoreText; bool isCalledOnce = false; public void GameOver(){ if (!isCalledOnce) { isCalledOnce = true; GameObject.Find ("PanelScript").GetComponent().Stopgame(); GameObject.Find ("player").GetComponent ().Deleteplayer(); } } public void AddScore(){ this.score += 1; } void Start () { this.scoreText = GameObject.Find ("Score"); } void Update () { scoreText.GetComponent ().text = "Score:" + score.ToString("D4"); } }
ゲームオーバーの処理は最初に敵がステージを通り越した時に1度だけ行いたい。そのため、1回だけ実行したい処理をif文内に記述し、同ブロック内でboolの値を切り替える。Updateメソッドはフレームごとに繰り返し実行されるが、このifのブロックは1回しか実行されない。
bool isCalledOnce = false; public void GameOver(){ if (!isCalledOnce) { isCalledOnce = true;
ifのブロック内にゲームオーバー 時に行いたい処理を記述する。一つ目は「PlayerController」内に記述されたDeleteplayer関数を呼び出す。(=プレイヤーを消す。)二つ目は「PanelManager」に記述されたStopgame関数を呼び出す。(=ゲームオーバーパネルを表示する。)
//プレイヤーを消し GameObject.Find ("player").GetComponent().Deleteplayer(); //ゲームオーバーパネルを表示する GameObject.Find ("PanelScript").GetComponent ().Stopgame();
最後にゲームオーバーを判定するスクリプトを記述する。今回のゲームオーバー判定は敵を撃ち損なうなので、敵が弾に当たらずステージ下まで行ってしまったら負け、ということになる。そこで敵の動きを処理している「EnemyController」を開き、赤字の一文を追記する。スクリプトはこちらから。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class EnemyController : MonoBehaviour{
float fallSpeed;
float rotSpeed;
public void Start () {
this.fallSpeed = 0.01f + 0.1f * Random.value;
this.rotSpeed = 6f + 3f * Random.value;
}
public void Update () {
transform.Translate( 0, -fallSpeed, 0, Space.World);
transform.Rotate(0, 0, rotSpeed );
if (transform.position.y < -5.5f) {
Destroy (gameObject);
GameObject.Find ("Canvas").GetComponent ().GameOver ();
}
}
}
敵がステージの下の端まで行ったら敵を消す、のスクリプトに続けて、ステージ上の「Canvas」にアタッチされているスクリプト「GameSystem」の中に記述されたGameOver関数の処理を行うよう命令している。
動作確認をする
保存してゲームビューで動作確認をする。ゲームオーバーになると、プレイヤーが消えて「GAMEOVER」の文字が表示される。
次回の「Step9:リトライボタンの設定」ではここにゲームをリロードするためのリトライボタンをつけていく。
★チュートリアル一覧
2020.6.3投稿