【第11回】ゲームクリア&ゲームオーバー処理の作り方

前回までの作業で敵キャラが出現する処理を作ることができました。そこでそろそろゲームクリアやゲームオーバーといった「ゲームの流れ」部分を作っていこうと思います。

今回のゲーム「ゾンビスレイヤー2」では

  • 敵キャラを一定数倒せばゲームクリア
  • 敵キャラが拠点に侵入したらゲームオーバー

という流れにしたいので、これを踏まえて処理を作っていきましょう。

スポンサーリンク

必要なUIの作成

では、まずは必要なUIを作っていきます。作るUIは次の3つです。

  1. 倒した敵の数を表示するUI
  2. ゲームクリア表示用のUI
  3. ゲームオーバー表示用のUI

このうち2と3の作り方は全く同じなので、1と2の作り方を説明していきますね。

倒した敵の数を表示するUI

倒した敵の数を表示するUIの例

キャンバスを用意して、画面上部にテキストを1つ配置するだけです。

ゲームクリア表示用のUI

ゲームクリア表示用のUIの例

画面中央やや上にテキストを配置し、その下にボタンを1つ配置してください。ゲームオーバー用のUIもこれとほぼ同じなので、複製してテキストの文字を「Game Over」に変更すればOKです。

作れたらゲームクリア用・ゲームオーバー用のどちらも「Canvas」コンポーネントのチェックを外してキャンバスを非表示にしておきましょう。

GameManagerの作成

次に、ゲームの流れを制御するための「GameManager」というゲームオブジェクトを作ります。一口にゲームの流れを制御する、といってもその内容はゲームによって様々ですが、今回は次のような処理を担うものとしておきます。

  • 倒した敵キャラの数をカウントする
  • ゲームクリア表示用のUIを表示する
  • ゲームオーバー表示用のUIを表示する
  • リトライ処理を行う

GameManagerのC#スクリプト

では早速ですがGameManagerのC#スクリプトは次の通りです。新しいC#スクリプトを作り、名前を「GameManager」に変更してコードを記入してください。

using UnityEngine;
using UnityEngine.UI;
using UnityEngine.SceneManagement;

public class GameManager : MonoBehaviour
{

  [SerializeField]
  FpsGunControler gunController = null;
  [SerializeField]
  Canvas gameClearCanvas = null;
  [SerializeField]
  Canvas gameOverCanvas = null;
  [SerializeField]
  Text countText = null;
  [SerializeField, Min(1)]
  int maxCount = 30;

  bool isGameClear = false;
  bool isGameOver = false;
  int count = 0;

  public int Count
  {
    set
    {
      count = Mathf.Max(value, 0);

      UpdateCountText();

      if(count >= maxCount)
      {
        GameClear();
      }
    }
    get
    {
      return count;
    }
  }

  void Start()
  {
    count = 0;

    UpdateCountText();
  }

  public void GameClear()
  {
    if(isGameClear || isGameOver)
    {
      return;
    }

    gunController.enabled = false;
    gameClearCanvas.enabled = true;
    Cursor.lockState = CursorLockMode.None;

    isGameClear = true;
  }

  public void GameOver()
  {
    if (isGameClear || isGameOver)
    {
      return;
    }

    gunController.enabled = false;
    gameOverCanvas.enabled = true;
    Cursor.lockState = CursorLockMode.None;

    isGameOver = true;
  }

  public void Retry()
  {
    SceneManager.LoadScene(0);
  }

  public void UpdateCountText()
  {
    countText.text = count.ToString() + " / " + maxCount.ToString();
  }
  
}

特に難しい処理はないので解説は不要だと思います。すぐには分からないという方も、コードをよく読んで処理の内容を考えてみてください。

必要な設定を行う

さてスクリプトが書けたら、新しい空のゲームオブジェクトを作って先ほどのスクリプトをアタッチし、このゲームオブジェクトのタグを最初からある「GameController」にしておきましょう(※このあと別のゲームオブジェクトから検索するときに使うので必ず設定してください)。また、GameManagerコンポーネントの空欄部分に該当するコンポーネント等を設定しておいてください。

それから、先ほど作ったゲームクリア用UI・ゲームオーバー用UIのボタンにまだ何も割り当てていなかったので、「Button」コンポーネントの「クリック時()」の欄にGameManagerの「Retry」関数を登録しておきましょう(下図)。

ボタンに処理を割り当てた場合の例

これでボタンをクリックするとシーンが再読み込みされてゲームが再スタートするようになります。

敵キャラクターのC#スクリプトの変更

次に、まだ敵キャラクターを倒したときにカウントが増えるようになっていないので、敵キャラのC#スクリプトにその処理を追加します。「EnemyController」スクリプトを開き、次の「★変更4」と書かれた部分を追加しましょう(※無関係な部分はバッサリ省略してあります)。

// 省略

// ★変更2
bool isAttacking = false;
Transform player;
Transform defaultTarget;
WaitForSeconds attackWait;
WaitForSeconds attackIntervalWait;

// ★変更4
GameManager gameManager;

public int Hp
{
  set
  {
    hp = Mathf.Clamp(value, 0, maxHp);
  }
  get
  {
    return hp;
  }
}

// ★変更3
public Transform Target
{
  set
  {
    target = value;
  }
  get
  {
    return target;
  }
}

// ★変更4
GameManager GameManager
{
  get
  {
    if(gameManager == null)
    {
      gameManager = GameObject.FindGameObjectWithTag("GameController").GetComponent<GameManager>();
    }

    return gameManager;
  }
}

// 省略

// 死亡時の処理
void Dead()
{
  isDead = true;
  capsuleCollider.enabled = false;
  animator.SetBool(DeadHash, true);

  // ★変更2
  StopAttack();
  navmeshAgent.isStopped = true;

  // ★変更4
  GameManager.Count++;

  StartCoroutine(nameof(DeadTimer));
}

// 以下省略

ゲームオーバーゾーンの作成

最後に、「敵キャラが拠点に侵入したらゲームオーバー」となるように敵が触れたらゲームオーバーになるトリガーを作ろうと思います。

新しく空のゲームオブジェクトを作り、適当なコライダーをアタッチしたら「トリガーにする」にチェックを入れておいてください。

ゲームオーバーゾーンのC#スクリプト

そうしたらゲームオーバーゾーン用のごく簡単なC#スクリプトを書きます。新しいC#スクリプトを作成し、名前を「GameOverZone」に変更して次のコードを書いてください。

using UnityEngine;

[RequireComponent(typeof(Collider))]
public class GameOverZone : MonoBehaviour
{

  [SerializeField]
  GameManager gameManager = null;

  void OnTriggerEnter(Collider other)
  {
    if (other.gameObject.CompareTag("Enemy"))
    {
      gameManager.GameOver();
    }
  }

}

できたらこれを先ほど作ったゲームオブジェクトにアタッチして、「GameManager」欄にゲームマネージャーを登録しましょう。

敵キャラにRigidbodyを追加する

さて、第8回でキャラクターを動かせるようにしたときに「今回はRigidbodyは不要です」というような話をした気がしますが、キャラクターにRigidbodyがないとOnTriggerEnterが呼ばれないのでやっぱりRigidbodyは必要です。

ただし物理演算そのものは不要なので、Rigidbodyコンポーネントの「Is Kinematic」にチェックを入れて物理演算を無効化しておきましょう。

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

ここまでできたらテストプレイして動作を確認しましょう。

  • 敵キャラを倒すとカウントが増える
  • カウントが一定値に達したらゲームクリア画面が出る
  • 敵がゲームオーバーゾーンに到達したらゲームオーバー画面が出る

といった項目を確認してください。


次のページ→ステージ作成&敵キャラの種類を増やす