さて、これで一通りステージを作れるようになったので、この辺でゲームの進行上とても重要な処理を作ります。それはステージの切り替え処理です。せっかくステージをたくさん作ってもその間を移動できなければ意味がありません(´・ω・`)
Unityにはシーン切り替え機能があるので、それを使ってステージ間を移動する処理を実現してみましょう。
GameManagerオブジェクトを作る
まず、シーンの切り替えなどゲームの裏方的な存在をするゲームオブジェクトを作ります。空のゲームオブジェクトを作り、名前を「GameManager」に変更してください。そうしたら新しいC#スクリプトファイルを作り、名前を「GameManager」に変更してGameManagerオブジェクトにアタッチしてください。
GameManagerのプログラム
GameManager.csに次のソースコードを記入してください。今回はシーンの切り替えを行うので先頭のほうに「using UnityEngine.SceneManagement;」と書いておきます。
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.SceneManagement; public class GameManager : MonoBehaviour { [System.NonSerialized] public int currentStageNum = 0; //現在のステージ番号(0始まり) [SerializeField] string[] stageName; //ステージ名 //最初の処理 void Start () { //シーンを切り替えてもこのゲームオブジェクトを削除しないようにする DontDestroyOnLoad(gameObject); } //毎フレームの処理 void Update () { } //次のステージに進む処理 public void NextStage() { currentStageNum += 1; //コルーチンを実行 StartCoroutine(WaitForLoadScene()); } //シーンの読み込みと待機を行うコルーチン IEnumerator WaitForLoadScene() { //シーンを非同期で読込し、読み込まれるまで待機する yield return SceneManager.LoadSceneAsync(stageName[currentStageNum]); } //ゲームオーバー処理 public void GameOver() { } }
プログラムの解説
最初の処理
通常、シーンが切り替わるとそのシーン内のゲームオブジェクトは削除されてしまいます。しかしGameManagerは現在のステージの番号などを保持しているため、削除してしまうとゲームが進まなくなってしまいます。そこで「DontDestroyOnLoad」でシーンが切り替わってもGameManagerが削除されないようにしましょう。
次のステージに進む処理
現在のステージ番号を+1してコルーチンを実行します。
コルーチン
先頭に「IEnumerator」がついたメソッドはコルーチンと呼ばれるもので、処理を一定時間待ちたいときに便利です。ここではシーンをバックグラウンドで読み込んで、その間の時間だけ待つという処理を行っています。
なお、シーンを非同期で読み込みたいときは「SceneManager.LoadSceneAsync」を使います。このように非同期で読み込む理由は、万一ステージの読み込みに時間がかかった場合でも安全にステージを切り替えることができるからです(SceneManager.LoadSceneだと読み込んでいる最中でも入力を受け付けてしまいます)。
Goalのプログラムの変更
最後に、ゴールのプログラムを変更してプレイヤーがゴールに到着したときに次のステージに切り替わるようにします。Goal.csを次のように変更してください。
using System.Collections; using System.Collections.Generic; using UnityEngine; public class Goal : MonoBehaviour { GameManager gameManager; void Start() { gameManager = GameObject.Find("GameManager").GetComponent<GameManager>(); } //プレイヤーが当たり判定に入った時の処理 void OnTriggerEnter(Collider other) { if(other.gameObject.tag == "Player") { gameManager.NextStage(); } } }
ここまでの注意点
プログラムの解説の通り、GameManagerはシーンが切り替わっても削除されません。なのでテストプレイの際、1つのステージだけをテストプレイするときは(Goalオブジェクトから参照するため)GameManagerオブジェクトを作っておく必要があるのですが、通しプレイするときにGameManagerを各ステージに置いておくとGameManagerが重複してしまい問題が発生する可能性があります。このことを覚えておいてください。
ちなみに、プログラミング的には「シングルトン」(シーンに一つしか存在しないオブジェクト)という考え方があり、それを導入することでこの問題を解決できます。ですがプログラムが少し難しくなるのでここでは割愛します。気になる方は中級コースの「コインを集めて!ユニティちゃん」の記事「シングルトンなゲーム管理オブジェクトの作り方」を参照してください。
シーンを登録する
さて、ひとまずシーン切り替え処理ができたので、あとは必要なシーンを登録します。
まず、メニューバーで「File」→「Build Settings」を開いてください。ビルド設定にはビルドするシーンを登録する部分があるので、ここにシーンを登録していきましょう(登録しないと実際のゲームでシーンを読み込めないので注意してください)。
次にGameManagerのほうにシーン名を登録します。Stage Nameに必要なだけステージのシーンファイル名を登録してください(このリストの順番でステージを進めていきます)。また、このときファイル名を間違えると読み込みに失敗するのでご注意ください(本当はシーンファイルを直接インスペクタに登録できればいいのですが、標準でそういう機能はないのでこういうやり方をしています)。
シーン切り替えの問題点
それではテストプレイしてみましょう。ステージが切り替われば成功です。ただし、プレイしてみると分かるのですがシーンが一瞬で「パッと」切り替わってしまいます。
実はこれが標準の仕様なので、切り替えのときにフェードさせたりしたい場合は自分で作る必要があるのです。そこで次のページではシンプルなフェード処理を作ります。
次のページ→簡単なトランジションを作る