シンプルなアクションゲームを作ってみようの第24回です。
今回はゲーム開始前のカウントダウン機能を作成していきます。
前回はCinemachineを使ってカメラを操作し、プレイヤーキャラクターを追いかけるようにしました。
シンプルなアクションゲームを作ってみようの他の記事は
シンプルなアクションゲームを作るのを通してUnityの使い方を学ぶカテゴリです。
から参照出来ます。
カウントダウン機能を作成する
ここまでに出来ているStage1シーンのゲームではUnityエディターでプレイボタンを押すとすぐにゲームが開始されています。
しかしシーンが始まってすぐにゲームが開始されるのはユーザーにとっては準備が整っていない事もあると思います。
そこでゲーム開始までの数秒をカウントダウン表示し、ゲーム開始前の準備が出来るようにします。
カウントダウン用のUIの作成
まずはカウントダウン用のUIを作成していきます。
Stage1シーンのヒエラルキーのUIを選択した状態で右クリックからUI→Canvasを選択し、名前をCountDownとします。
CountDownゲームオブジェクトを選択した状態で右クリックからUI→Text – TextMeshProを選択し、名前をCountDownTextとします。
CountDownTextのインスペクタでは以下のように設定します。
Rect TransformのWidthを400、Heightを50にします。
TextMeshProのFont Sizeを72、Vertex Colorの色を赤色にします。
AlignmentのCenterとMiddleを押し、テキストをゲーム画面の中央に配置します。
カウントダウン表示するスクリプト
カウントダウン表示をする処理はGameManagerスクリプトに書いていきます。
1 2 3 4 | using TMPro; using UnityEngine.SceneManagement; |
usingディレクティブでTMProとUnityEngine.SceneManagementを指定します。
1 2 3 4 5 6 | // カウントダウン中かどうか public bool IsCountDown { get; set; } // カウントダウン数字を表示するテキスト private TextMeshProUGUI countDownText; |
IsCountDownプロパティはカウントダウン中かどうかのフラグです。
countDownTextには先ほど作ったCountDownTextゲームオブジェクトを取得し入れます。
1 2 3 4 5 6 7 8 | void Start() { countDownText = GameObject.Find("CountDownText").GetComponent<TextMeshProUGUI>(); // ゲーム関連初期化 IsCountDown = true; StartCoroutine(CountDown()); } |
Startメソッドでは
最初にCountDownTextというゲームオブジェクトを探し、そこからTextMeshProUGUIコンポーネントを取得します。
IsCountDownをtrueにし、カウントダウンを開始するとします。
StartCoroutineメソッドを使ってCountDownメソッドを実行します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | // カウントダウン表示 IEnumerator CountDown() { // ステージ名の表示 countDownText.text = SceneManager.GetActiveScene().name; // ここから1秒経過毎に数字を更新 yield return new WaitForSeconds(1f); countDownText.text = "3"; yield return new WaitForSeconds(1f); countDownText.text = "2"; yield return new WaitForSeconds(1f); countDownText.text = "1"; yield return new WaitForSeconds(1f); countDownText.text = "Start"; IsCountDown = false; yield return new WaitForSeconds(0.5f); countDownText.gameObject.SetActive(false); } |
コルーチンは1つのフレーム内で実行される機能で一定時間を経過した後にその後の処理から順次実行したい時や一定時間毎に何らかの処理をしたい時等に使えます。
CountDownメソッドではIEnumeratorを返します。
コルーチンを使う時はこれを返します。
最初にSceneManager.GetActiveSceneメソッドで現在アクティブなシーンを取得し、nameプロパティでその名前を取得します。
今回の場合はStage1シーンしか作ってないのでStage1というシーン名がcountDownText.textに入ります。
その後yieldというキーワードを使ってWaitForSecondsのインスタンス生成時に1fを渡して生成します。
1 2 3 | yield return new WaitForSeconds(1f); |
これで1秒間実行を停止します。
その後countDownTextに3という表示をし、また1秒待つというのを何度か繰り返します。
最後にStartという文字列をcountDownTextに表示したらIsCountDownをfalseにし、0.5秒待った後countDownTextのゲームオブジェクトをSetActiveメソッドでfalseにして見えないようにします。
1秒間待つという処理を4回行っていて、毎回インスタンスを生成しているので、あらかじめインスタンスを生成しておいてそれを利用する方が良いかもしれません。
例えば、フィールドや変数を用意し、生成したインスタンスを入れておきます。
1 2 3 | private WaitForSeconds waitTime = new WaitForSeconds(1f); |
以下のようにCountDownメソッド内で変数にインスタンスを保持し、その後waitTimeを使う方が何度もインスタンス化するよりも無駄がないかもしれません。
1 2 3 4 5 6 7 | // カウントダウン表示 IEnumerator CountDown() { var waitTime = new WaitForSeconds(1f); // その他の処理 } |
後はコルーチンの中で毎回同じ処理をしていた部分にwaitTimeを使用します。
1 2 3 | yield return waitTime; |
これでカウントダウン表示が出来るようになりました。
他のスクリプトでカウントダウンが終わるのを待つ処理を追加する
カウントダウン表示は出来ましたが、カウントダウンが表示し終わる前に移動や時間が経過してしまいます。
そこでGameManagerのIsCountDownプロパティがtrueの時は移動や時間計測を行わないようにします。
カウントダウン表示時も移動を行いたい時等はそういった条件を加える必要はありません。
PlayerControllerに処理を追加する
まずはPlayerControllerスクリプトに処理を追加します。
1 2 3 4 5 6 7 | // Update is called once per frame void Update() { if (gameManager.IsCountDown) { return; } |
Updateメソッドの一番最初にgameManager.IsCountDownでカウントダウン中かどうか判断し、カウントダウン中であればreturnでそれ以降の処理を実行しないようにします。
EnemyControllerに処理を追加する
次は敵の操作をするEnemyControllerスクリプトに処理を追加します。
1 2 3 4 5 6 | void Update() { if (gameManager.IsCountDown) { return; } |
Updateメソッドの最初にgameManager.IsCountDownを調べカウントダウン中であればreturnでそれ以降の処理をしないようにします。
TimerScriptに処理を追加する
次は時間計測をするTimerScriptに処理を追加します。
1 2 3 4 5 6 7 | void Update() { // ゲームオーバー時は以降何もしない if (gameManager.IsCountDown || gameManager.GameOver) { return; } |
Updateメソッドの最初でgameManager.GameOverだけで判断していた部分にgameManager.IsCountDownを追加し、どちらかの条件に当てはまればreturnでそれ以降の処理をしないようにします。
FireBulletScriptに処理を追加する
次は大砲から弾を発射する処理を書いているFireBulletScriptに処理を追加します。
1 2 3 4 5 6 7 | void Update() { // カウントダウン中やゲームオーバー時は以降何もしない if (gameManager.IsCountDown || gameManager.GameOver) { return; } |
Updateメソッド内のgameManager.GameOverだけで判断していた部分にgameManager.IsCountDownを追加し、どちらかの条件が成立したらreturnでそれ以降の処理をしないようにします。
実行して確認してみる
機能が出来たので実行して確認してみましょう。
上のようにカウントダウン表示がされ、カウントダウン中は移動や弾の発射がされないようになりました。
終わりに
今回はゲーム開始前のカウントダウン表示機能を作成しました。
次回はシーンにエフェクトを加えていきます。