【Unity】ゲームオーバー処理の作り方(ゲームの作り方チュートリアル「悪路王」その6)

悪路王 ゲームオーバー ゲームの作り方

前回までの作業でゲームとしては大体良い感じになってきました。しかしまだゲームオーバーなどの処理を実装していないため、ミスをしてもキャラクターが画面端から落ちていくだけでゲームがそのまま続いてしまいます。

そこでここでは

  • プレイヤーがミスをしたらゲームオーバー画面を表示し、ゲームを中断する
  • 「リトライ」ボタンを押したらゲームがリセットされて最初からゲームが始まる

といった処理を作っていきましょう。

ゲームオーバー画面のUIの作り方

まずはじめにゲームオーバー画面のUIを作ります。前回と同じ要領で新しいキャンバスを作り、「Game Over」というテキストを配置してください。また、その下にボタン(こちらも右クリック→「UI」→「古い機能」の中のものを使います)も配置してください。

ゲームオーバー画面の例

できたら、このままではゲームオーバーでないときも表示されてしまい邪魔なのでキャンバスのゲームオブジェクトを非アクティブにしておきましょう。

ゲームオーバー処理のC#スクリプト

ではここでゲームオーバー処理のC#スクリプトを書いていきます。ゲームオーバー処理はゲーム進行に関わる処理なので、前回作ったGameManagerに処理を追加することにしましょう。

以下は「追加」と書かれている部分が追加部分です。なおすべてのソースコードを掲載すると長くなってしまうので適宜省略してあります。

using System.Collections;
using UnityEngine;
using UnityEngine.UI;

public class GameManager : MonoBehaviour
{

    [Header("必要なコンポーネントを登録")]
    [SerializeField]
    Transform playerTransform;
    [SerializeField]
    WallSpawner wallSpawner;
    [SerializeField]
    Text mileageText;
    [SerializeField]
    Text scoreText;
    [SerializeField]
    Text highScoreText;
    [SerializeField]
    Text levelText;
    // 追加
    [SerializeField]
    GameObject gameOverCanvas;

    // 省略

    // 追加
    readonly string highScoreKey = "highScore";

    // 省略

    void InitGame()
    {
        Level = 1;
        Mileage = 0;
        maxScore = (int)Mathf.Pow(10, scoreDigits) - 1; //スコアの最大値を作成。例えば、8桁なら99999999
        score = 0;
        highScore = PlayerPrefs.GetInt(highScoreKey, 0);	//追加
        timerIsActive = false;

        UpdateScoreUi();
        wallSpawner.InitSpawner();
    }

    // 省略

    // ここから追加
    public void GameOver()
    {
        playerTransform.gameObject.SetActive(false);
        wallSpawner.IsActive = false;
        gameOverCanvas.SetActive(true);

        if(timer != null)
        {
            StopCoroutine(nameof(MileageTimer));
            timerIsActive = false;
        }

        IsActive = false;

        // ハイスコアのセーブ
        if(highScore > PlayerPrefs.GetInt(highScoreKey, 0))
        {
            PlayerPrefs.SetInt(highScoreKey, highScore);
            PlayerPrefs.Save();
        }
    }

    public void Retry()
    {
        gameOverCanvas.SetActive(false);

        StartGame();
    }

}

書けたら追加した「Game Over Canvas」欄にゲームオーバー用のキャンバスを登録しておきます。また、このままだとリトライボタンを押しても何も起きないので、ボタンを押したときにリトライ処理が実行されるようにボタンの「クリック時()」の欄にRetry関数を登録しておきましょう。

ボタンを押したらリトライ処理が行われるようにする

C#スクリプトの解説

追加した処理に関しても特に難しいことはやっていないのでコードを読んで頂ければわかると思うのですが、1点だけ注意点があります。それは「本当はPlayerPrefsは使うべきではない」という点です。

PlayerPrefsとはUnity標準のセーブ機能のことで、標準機能なのになんと色々な問題点があります。詳しい話は姉妹サイトのほうでしているのでここでは省略しますが…

【Unity】できれば「使わない方がいい」Unityの機能ワースト3
Unityを使っていると、ある機能についてよく調べたときに公式が「その機能は使うな」みたいなことを平気で言っていることがあります。個人的には機能を提供しておいてそれはねーだろ…と思うわけですが、Unityでは「あまり良くない機能だが、分かり

簡単に言うと

  • 動作が遅い
  • 保存できるデータの型が限られていて不便
  • セーブデータの保存場所がレジストリになる場合がある

とかまあそういう欠点があるわけです。

それで今回はなるべく簡単なコードになるようにと考えた結果として、やむなくハイスコアのセーブ処理にPlayerPrefsを使うことにしました。しかしこういう練習作のようなゲームならともかく、もし本格的にゲームを作るならちゃんとしたセーブ機能を導入したほうがよいということはお伝えしておきます。

ゲームオーバー判定用のトリガーの作成

さてこれでゲームオーバー処理ができましたが、まだゲームオーバー処理を呼び出すための仕組みを作っていないので何も起きません。そこでゲームオーバー判定用のトリガーを作りましょう。

まず空のゲームオブジェクトを作成し、そこに「Box Collider 2D」コンポーネントをアタッチしてサイズを適当に大きくし、「トリガーにする」にチェックを入れます。

トリガーの作り方

次にゲームオーバー処理を呼び出すためのC#スクリプトを作ってこのゲームオブジェクトにアタッチします。

using UnityEngine;

public class GameOverTrigger : MonoBehaviour
{

    [SerializeField]
    GameManager gameManger;

    private void OnTriggerEnter2D(Collider2D collision)
    {
        if (collision.gameObject.CompareTag("Player"))
        {
            gameManger.GameOver();
        }
    }

}

そうしたら下の図のようにこのトリガーをシーンの左端に配置しておきましょう。

ゲームオーバー用トリガーの配置例

テストプレイして動作を確認しよう

では最後にテストプレイして動作を確認してみましょう。

  • プレイヤーが画面端に押し出されたらゲームオーバー画面が出る
  • リトライボタンを押したらゲームが再スタートする
  • 一度再生モードを終了してもハイスコアがきちんと保存される

といった点をチェックしておいてください。

悪路王 ゲームオーバー処理の例

(画像クリックでGIF再生)

次のページ

【Unity】スクロールする背景の作り方(ゲームの作り方チュートリアル「悪路王」その7)
前回までの作業でゲームの流れを完成させることができたので、とりあえず最低限ゲームとして成り立つようになりました。ただしまだゲームとしては寂しい部分があるので、ここからもう少し手を加えてブラッシュアップしていきます。 作業したい部分はいくつか...