前回までの作業で、ゲームの大きな流れを監督するGameManagerの機能の一部を作ることができました。しかし、まだゲームオーバー処理を作っていないので、プレイヤーが画面外に押し出されてしまってもそのままゲームが続いてしまいます。
そこで、ここでは
- ゲームオーバー画面のUI
- ゲームオーバー処理・リトライ処理
といった部分を作っていきましょう。
ゲームオーバー画面のUIの作成
では、まずはゲームオーバー画面用のUIを作っていきます。「くろくま基本アセット」が導入してあれば、「Prefabs」→「UI」→「Canvas」内に「Canvas」という設定済みのキャンバスのプレハブがあるので、それにUIを付け加えて作りましょう。
Canvasプレハブをシーンにドラッグ&ドロップしたら、名前を「GameOverCanvas」に変更して、下の図のようにテキストとボタンを追加してください。
この2つのUIの名前は次のように設定しましょう。
- 「GameOver」のテキスト:GameOverText
- リトライ用ボタン:RetryButton
ボタンのほうはスクリプトから検索するので間違えないようにしてください。
できたら下の図のように「Canvas」コンポーネントのチェックをOFFにしてキャンバスを非表示にし、これを「Canvas」フォルダにドラッグ&ドロップしましょう。
このときプレハブバリアント(=派生プレハブ)にするかどうか聞かれるので、バリアントにするようにします。そうするとプレハブの名前が「(プレハブの名前) Variant」という風になり余分な文字が追加されてしまうので、それを削除しておきましょう。
ゲームオーバー&リトライ処理の作成
次に、GameManagerを変更してゲームオーバー処理やリトライ処理を作ります。GameManagerスクリプトを次のように変更しましょう(※関係ないところは省略してあります)。
//省略 //--ここから追加-- [Header("ゲーム設定")] [SerializeField] int maxLevel = 10; [SerializeField, Min(1), Tooltip("LvUp毎に障害物の生成間隔を小さくするための除数")] float divisor = 1.1f; [SerializeField, Tooltip("スコアの桁数")] int scoreDigits = 8; [SerializeField] Vector2 playerSpawnPosition = Vector2.zero; [SerializeField, Tooltip("1メートルを何秒で走るか")] float secondsPerMeter = 0.05f; [SerializeField, Tooltip("1メートル走った時に加算される基本スコア")] int scorePerMeter = 10; [SerializeField, Tooltip("レベルアップに必要な走行距離")] int meterPerLevel = 100; [Header("UIの設定")] [SerializeField] string mileageTextName = "MileageText"; [SerializeField] string scoreTextName = "ScoreText"; [SerializeField] string highScoreTextName = "HighScoreText"; [SerializeField] string levelTextName = "LvText"; [SerializeField] string gameOverCanvasName = "GameOverCanvas(Clone)"; //追加その2 [SerializeField] string retryButtonName = "RetryButton"; //追加その2 //--追加ここまで-- MoveSceneManager moveSceneManager; SaveManager saveManager; SoundManager soundManager; //--ここから追加-- bool timerIsActive = false; int level = 1; int mileage = 0; //走行距離 int maxScore = 0; int score = 0; int highScore = 0; Text mileageText; Text scoreText; Text highScoreText; Text levelText; WallSpawner wallSpawner; Coroutine timer; Canvas gameOverCanvas; //追加その2 Button retryButton; //追加その2 GameObject playerObj; //追加その2 //省略 //--ここから追加-- public void InitGame() { level = 1; mileage = 0; maxScore = (int)Mathf.Pow(10, scoreDigits) - 1; //スコアの最大値を作成。例えば、8桁なら99999999 score = 0; timerIsActive = false; } public void GameStart() { InitGame(); } public void GameOver() { if(playerObj != null) { Destroy(playerObj); } timerIsActive = false; wallSpawner.isActive = false; gameOverCanvas.enabled = true; } public void Retry() { //シーンにある障害物を全部消去する GameObject[] walls = GameObject.FindGameObjectsWithTag("Wall"); foreach(GameObject wall in walls) { Destroy(wall); } gameOverCanvas.enabled = false; GameStart(); } //省略 //シーン読み込み時に各種コンポーネントを取得するメソッド public void LoadComponents() { if (moveSceneManager.SceneName == "Title") { return; } wallSpawner = GameObject.FindGameObjectWithTag("Spawner").GetComponent<WallSpawner>(); mileageText = GameObject.Find(mileageTextName).GetComponent<Text>(); scoreText = GameObject.Find(scoreTextName).GetComponent<Text>(); highScoreText = GameObject.Find(highScoreTextName).GetComponent<Text>(); levelText = GameObject.Find(levelTextName).GetComponent<Text>(); //追加その2 gameOverCanvas = GameObject.Find(gameOverCanvasName).GetComponent<Canvas>(); retryButton = GameObject.Find(retryButtonName).GetComponent<Button>(); //ボタンにクリック時の処理を登録 retryButton.onClick.AddListener(() => Retry()); }
この後の作業の都合上まだ完成ではないのですが、ゲームオーバーやリトライの一応の処理の流れはできました。
変更できたら、GameManagerオブジェクトをインスペクターで開いて、「プレハブ」欄に「GameOverCanvas」を登録してください(下図)。
これでシーンにGameOverCanvasを置いておく必要がなくなったので削除しておきましょう。
ゲームオーバー判定用のトリガーの作成
さて、これでゲームオーバー処理はできたのですが、それを呼び出す処理を書いていないのでまだ何も起こりません。そこで、プレイヤーキャラが接触したらゲームオーバー処理を呼び出すようなトリガーを作ります(下図)。
シーンに空のゲームオブジェクトを作り、名前を「GameOverTrigger」に変更して2Dボックスコライダーをアタッチし、次のように設定してください。
- 座標:(-9, 0, 0)
- ボックスコライダーのサイズ:(1, 10)
そうしたら、C#スクリプトを書いてプレイヤーが接触したときにゲームオーバー処理を呼び出すようにします。新しいC#スクリプトを作り、名前を「GameOverTrigger」にしたら次のスクリプトを書いてください。
using System.Collections; using System.Collections.Generic; using UnityEngine; public class GameOverTrigger : MonoBehaviour { GameManager gameManager; void Start() { gameManager = GameObject.FindGameObjectWithTag("GameController").GetComponent<GameManager>(); } //プレイヤーが触れたらゲームオーバーにする void OnTriggerEnter2D(Collider2D collision) { if (collision.gameObject.CompareTag("Player")) { gameManager.GameOver(); } } }
簡単なスクリプトなので説明はいらないと思います。書けたらこれを先ほど作ったGameOverTriggerオブジェクトにアタッチしましょう。
ここまできちんとできていれば、ゲームを実行したときに次のGIFのようになるはずです。
ただし、まだ
- ゲームオーバーになってもプレイヤーキャラが削除されない
- リトライがうまく機能しない
といった問題があります。これらの点については次のページで修正していきますね。
次のページ→カウントダウンの作り方