シーンの切り替えが一通りできたところで、コースから外れたときのゲームオーバー処理を作ってみましょう。
当たり判定の作成
まず、当たるとゲームオーバーになる領域を作ります。シーンに新しくPlaneを作り、名前を「GameOverZone」に変更してください。そうしたら、当たり判定だけ欲しいのでMesh Rendererコンポーネントを削除し、Mesh Colliderコンポーネントの「Convex」「Is Trigger」にチェックを入れてください。あとはScaleをステージ全体を覆うように変更し、PositionのYを調整してコースから外れたときだけこの当たり判定にあたるようにしてください。
GameOverZoneのプログラム
次にこの当たり判定のプログラムを書きます。新しいC#スクリプトを作り、名前を「GameOverZone」に変更したら先ほどの当たり判定にアタッチして、下記のソースコードを記入します。
using System.Collections; using System.Collections.Generic; using UnityEngine; public class GameOverZone : MonoBehaviour { GameManager gameManager; void Start () { gameManager = GameObject.Find("GameManager").GetComponent<GameManager>(); } //プレイヤーが当たり判定に入った時の処理 void OnTriggerEnter(Collider other) { if(other.gameObject.tag == "Player") { gameManager.GameOver(); } } }
ゲームオーバー画面のCanvasとUIの作成
次はゲームオーバー画面をuGUIで作ります。新しいCanvasを作り、名前を「GameOverCanvas」に変更したら下の図のようなUIを作成してください。
できたらこのCanvasをプレハブ化し、シーンからは削除してください。
GameManager.csの変更
最後にGameManagerのスクリプトを変更します。GameManager.csを下のように書き換えてください。
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.SceneManagement; using UnityEngine.UI; using UnityStandardAssets.Characters.ThirdPerson; using UnityStandardAssets.Cameras; public class GameManager : MonoBehaviour { [System.NonSerialized] public int currentStageNum = 0; //現在のステージ番号(0始まり) [SerializeField] string[] stageName; //ステージ名 [SerializeField] GameObject fadeCanvasPrefab; [SerializeField] GameObject gameOverCanvasPrefab; [SerializeField] float fadeWaitTime = 1.0f; //フェード時の待ち時間 GameObject fadeCanvasClone; FadeCanvas fadeCanvas; GameObject gameOverCanvasClone; ThirdPersonCharacter character; FreeLookCam freeLookCam; Rigidbody playerRigidbody; Button[] buttons; //最初の処理 void Start () { //シーンを切り替えてもこのゲームオブジェクトを削除しないようにする DontDestroyOnLoad(gameObject); //デリゲートの登録 SceneManager.sceneLoaded += OnSceneLoaded; //ユーザーコントロールとカメラコントロールを取得 character = GameObject.FindGameObjectWithTag("Player").GetComponent<ThirdPersonCharacter>(); playerRigidbody = GameObject.FindGameObjectWithTag("Player").GetComponent<Rigidbody>(); freeLookCam = GameObject.Find("FreeLookCameraRig").GetComponent<FreeLookCam>(); } //シーンのロード時に実行(最初は実行されない) void OnSceneLoaded(Scene scene, LoadSceneMode mode) { //改めて取得 character = GameObject.FindGameObjectWithTag("Player").GetComponent<ThirdPersonCharacter>(); playerRigidbody = GameObject.FindGameObjectWithTag("Player").GetComponent<Rigidbody>(); freeLookCam = GameObject.Find("FreeLookCameraRig").GetComponent<FreeLookCam>(); } //毎フレームの処理 void Update () { } //次のステージに進む処理 public void NextStage() { currentStageNum += 1; //コルーチンを実行 StartCoroutine(WaitForLoadScene(currentStageNum)); } //任意のステージに移動する処理 public void MoveToStage(int stageNum) { //コルーチンを実行 StartCoroutine(WaitForLoadScene(stageNum)); } //シーンの読み込みと待機を行うコルーチン IEnumerator WaitForLoadScene(int stageNum) { character.enabled = false; playerRigidbody.isKinematic = true; //フェードオブジェクトを生成 fadeCanvasClone = Instantiate(fadeCanvasPrefab); //コンポーネントを取得 fadeCanvas = fadeCanvasClone.GetComponent<FadeCanvas>(); //フェードインさせる fadeCanvas.fadeIn = true; yield return new WaitForSeconds(fadeWaitTime); //シーンを非同期で読込し、読み込まれるまで待機する yield return SceneManager.LoadSceneAsync(stageName[stageNum]); //フェードアウトさせる fadeCanvas.fadeOut = true; } //ゲームオーバー処理 public void GameOver() { //キャラやカメラの移動を停止させる character.enabled = false; playerRigidbody.isKinematic = true; freeLookCam.enabled = false; //ゲームオーバー画面表示 gameOverCanvasClone = Instantiate(gameOverCanvasPrefab); //ボタンを取得 buttons = gameOverCanvasClone.GetComponentsInChildren<Button>(); //ボタンにイベント設定 buttons[0].onClick.AddListener(Retry); buttons[1].onClick.AddListener(Return); } //リトライ public void Retry() { Destroy(gameOverCanvasClone); MoveToStage(currentStageNum); } //最初のシーンに戻る public void Return() { Destroy(gameOverCanvasClone); MoveToStage(0); } }
変更点の説明
シーンのロード時に実行
2つ目以降のシーンが読み込まれた時に実行します。このとき、改めてユニティちゃんのユーザーコントロールとカメラコントロールを取得しておきます(各ステージのユニティちゃんは全く同じですが、処理的には別物として扱っているため)。
任意のステージに移動する処理
次のステージに進む処理だけでは不便なので追加しました。
ゲームオーバー処理
まず、ゲームオーバーになった時にユニティちゃんを停止させておいたほうがいいので、ThirdPersonCaracterを無効化し、RigidbodyをKinematicにして動きを止めます。それからそのままではカメラの設定でマウスが表示されないのでFreeLookCamも無効化します。そうしたらゲームオーバー画面を表示し、その子であるボタンを取得してボタンをクリックしたときのイベントを登録します。
リトライ・最初のシーンに戻る
GameOverCanvasを消去してシーンを切り替えます。
ライティングの問題
さて、これで無事ゲームオーバーの処理ができたのですが、一つ問題があります。テストプレイしてもらうと分かる通り、リトライするとなぜかステージが暗くなってしまうのです。
私はこの問題でかなり悩みましたが、調べてみると解決方法がありました。メニューの「Window」→「Lighting」→「Setting」からライティングの設定を開き、「Object Maps」の「Auto Generate」のチェックを外して「Generate Lighting」をクリックしてください。これで事前にライティングが計算された状態になり、シーンを再読み込みしても暗くならないようになると思います。なお、この作業はすべてのステージで行ってください。
テストプレイして正常にリトライできれば成功です!
次のページ→タイトル画面を作る