ゲームの裏方部分の作り方(Part1:GameManagerの変更)

前回、クリア・ゲームオーバー表示用のキャンバスを作成しました。今回はゲーム進行を担うGameManagerのC#スクリプトを変更して、実際にクリアやゲームオーバーの表示が出るようにしていきます。


  • 今回の内容だけではエラーが出てしまうので、次のPart2の作業も併せて進めるようにしてください。
  • 初級コースにしてはやや難しめの内容ですが頑張りましょう。
スポンサーリンク

変更後のGameManager.csのC#スクリプト

では早速ですがGameManager.csを次のように書き換えてください。

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

[RequireComponent(typeof(MoveSceneManager))]
[RequireComponent(typeof(SaveManager))]
[RequireComponent(typeof(SoundManager))]
[DefaultExecutionOrder(-5)]
public class GameManager : SingletonMonoBehaviour<GameManager>
{

  [Header("シーンロード時に自動生成するプレハブを登録")]
  [SerializeField]
  GameObject[] prefabs = null;
  [SerializeField]
  AudioClip bgm = null;
  [SerializeField]
  AudioClip clearSe = null;
  [SerializeField]
  AudioClip gameOverSe = null;
  [SerializeField]
  string stageTextName = "StageText";
  [SerializeField]
  GameObject clearCanvasPrefab = null;
  [SerializeField]
  GameObject gameOverCanvasPrefab = null;
  [SerializeField]
  string nextButtonName = "NextButton";
  [SerializeField]
  string retryButtonName = "RetryButton";
  [SerializeField]
  string titleButtonName = "TitleButton";

  bool isClear = false;
  bool isGameOver = false;
  Text stageText;
  MoveSceneManager moveSceneManager;
  SaveManager saveManager;
  SoundManager soundManager;
  PlayerController player;

  protected override void Awake()
  {
    base.Awake();

    if (Debug.isDebugBuild)
    {
      
    }

    moveSceneManager = GetComponent<MoveSceneManager>();
    saveManager = GetComponent<SaveManager>();
    soundManager = GetComponent<SoundManager>();
  }

  void Start()
  {
    if (Debug.isDebugBuild)
    {
      InstantiateWhenLoadScene();
      ExecWhenLoadScene();
    }

    if (bgm != null)
    {
      soundManager.PlayBgmByName(bgm.name);
    }
  }

  void InitGame()
  {
    isClear = false;
    isGameOver = false;
  }

  public void Clear()
  {
    if (isClear)
    {
      return;
    }

    isClear = true;
    player.DestroyPlayer();

    if (clearSe != null)
    {
      soundManager.PlaySeByName(clearSe.name);
    }

    //次のステージのフラグが立っていなければ立ててセーブ
    if (moveSceneManager.CurrentSceneNum < moveSceneManager.NumOfScene - 1)
    {
      bool flag = saveManager.GetFlag(moveSceneManager.CurrentSceneNum + 1);

      if (!flag)
      {
        saveManager.SetFlag(moveSceneManager.CurrentSceneNum + 1);
        saveManager.Save();
      }
    }

    //クリア時のキャンバスを表示
    Instantiate(clearCanvasPrefab);
    Button nextButton = GameObject.Find(nextButtonName).GetComponent<Button>();
    Button titleButton = GameObject.Find(titleButtonName).GetComponent<Button>();

    //キャンバスのボタンにイベントを登録
    if (moveSceneManager.CurrentSceneNum >= moveSceneManager.NumOfScene - 1)
    {
      //最終ステージなら「次のステージ」ボタンを無効化
      nextButton.interactable = false;
    }
    else
    {
      nextButton.onClick.AddListener(() => moveSceneManager.MoveToScene(moveSceneManager.CurrentSceneNum + 1));
    }

    titleButton.onClick.AddListener(() => moveSceneManager.MoveToScene(0));
  }

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

    isGameOver = true;
    player.DestroyPlayer();

    if (gameOverSe != null)
    {
      soundManager.PlaySeByName(gameOverSe.name);
    }

    //ゲームオーバー時のキャンバスを表示
    Instantiate(gameOverCanvasPrefab);
    Button retryButton = GameObject.Find(retryButtonName).GetComponent<Button>();
    Button titleButton = GameObject.Find(titleButtonName).GetComponent<Button>();

    //ボタンにイベントを登録
    retryButton.onClick.AddListener(Retry);
    titleButton.onClick.AddListener(() => moveSceneManager.MoveToScene(0));
  }

  void Retry()
  {
    moveSceneManager.MoveToScene(moveSceneManager.CurrentSceneNum);
  }

  //シーンが読み込まれたときに登録したプレハブをInstantiateするメソッド
  public void InstantiateWhenLoadScene()
  {
    if (moveSceneManager.SceneName == "Title")
    {
      return;
    }

    foreach (GameObject prefab in prefabs)
    {
      Instantiate(prefab, transform.position, Quaternion.identity);
    }
  }

  //シーンが読み込まれたときに実行するメソッド
  public void ExecWhenLoadScene()
  {
    if (moveSceneManager.SceneName == "Title")
    {
      return;
    }

    LoadComponents();
    InitGame();
    UpdateStageUi();
  }

  void LoadComponents()
  {
    player = GameObject.FindGameObjectWithTag("Player").GetComponent<PlayerController>();
    stageText = GameObject.Find(stageTextName).GetComponent<Text>();
  }

  public void UpdateStageUi()
  {
    stageText.text = "ステージ" + moveSceneManager.CurrentSceneNum.ToString();
  }

}

C#スクリプトの解説

少し長めのスクリプトで、特にクリア時やゲームオーバー時の処理がややこしくなっています。

このスクリプトでやっていることは主に次の3つです。

  • シーン読み込み時のセットアップ
    (変数の初期化、メインキャンバス等の生成、必要なコンポーネントの取得など)
  • ゴールに触った時のクリア処理(PlayerControllerから呼ばれる)
    …クリア用キャンバスの表示やセーブ処理
  • 敵に触った時のゲームオーバー処理(PlayerControllerから呼ばれる)
    …ゲームオーバー用キャンバスの表示

C#スクリプトの流れ

シーンロード時

MoveSceneManager(※注)から次の2つのメソッドが呼ばれます(※タイトル画面を除く)。

  1. InstantiateWhenLoadScene()
  2. ExecWhenLoadScene()

ただし、今のところはExecWhenLoadSceneメソッドはMoveSceneManagerから呼ぶようにしていないので、あとで処理を追加する必要があります。


※注:MoveSceneManagerとは、「くろくま基本アセット」に含まれるシーンの移動を担うスクリプトのことです。

クリア時

登録されていれば効果音を鳴らし、セーブを行ってからクリア用キャンバスを表示します。

ただしクリア用キャンバスは動的に生成するため、ボタンには何もイベントが登録されておらず、そのままでは押しても何も起こりません。そこでAddListenerメソッドを使って、MoveSceneManagerのシーン移動用メソッドを登録します。

ゲームオーバー時

登録されていれば効果音を鳴らし、ゲームオーバー用キャンバスを表示します。

GameManagerコンポーネントの設定

スクリプトを変更できたら、GameManagerオブジェクトのGameManagerコンポーネントを次のように設定しましょう。

GameManagerコンポーネントの設定

BGMや効果音をつけたい場合はネットから適当な素材を探してインポート・登録してください。なお、サウンド素材のインポートの場所は「Resources」→「Audio」→「BGM」または「SE」にしてください。


次のページ→ゲームの裏方部分の作り方(Part2:各種スクリプトの変更)