ここまででゲームの基本的な流れができました。しかし、このままでは単にユニティちゃんを走らせるだけのゲームになってしまい単調なので、これからゲーム的な部分を作り込んでいく必要があります。今回はステージに制限時間を設けて緊張感が出るようにしてみましょう。
タイマーオブジェクトとタイマー用Canvasの作成
まず、空のゲームオブジェクトを作成して名前を「Timer」に変更し、その子として「Timer Canvas」というCanvasを作成してください。さらに、Timer Canvasの中に「00:00」と書かれたテキストと、フォントサイズを大きくした空のテキストを配置してください(下図参照)。
タイマー管理プログラム
次にタイマーの管理プログラムを作ります。「TimeManager」という名前のC#スクリプトを作り、Timerオブジェクトにアタッチしたら次のプログラムを記入します。
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; using UnityStandardAssets.Characters.ThirdPerson; [RequireComponent(typeof(CountDownTimer))] public class TimeManager : MonoBehaviour { [SerializeField] float waitTime = 2.0f; [SerializeField] Text readyGoText; CountDownTimer timer; ThirdPersonCharacter character; Rigidbody playerRigidbody; GameManager gameManager; void Start () { timer = GetComponent<CountDownTimer>(); character = GameObject.FindGameObjectWithTag("Player").GetComponent<ThirdPersonCharacter>(); playerRigidbody = GameObject.FindGameObjectWithTag("Player").GetComponent<Rigidbody>(); gameManager = GameObject.Find("GameManager").GetComponent<GameManager>(); StartCoroutine(ReadyGo()); } IEnumerator ReadyGo() { yield return new WaitForEndOfFrame(); //プレイヤーを停止させる character.enabled = false; playerRigidbody.isKinematic = true; yield return new WaitForSeconds(waitTime); readyGoText.text = "Ready?"; yield return new WaitForSeconds(waitTime); readyGoText.text = "GO!!"; //プレイヤーを移動可能にさせる character.enabled = true; playerRigidbody.isKinematic = false; //カウントダウン開始 gameManager.countDown = true; yield return new WaitForSeconds(waitTime); readyGoText.enabled = false; } }
カウントダウンタイマーのプログラム
次にタイマーのプログラムを作ります。「CountDownTimer」という名前のC#スクリプトを作り、Timerオブジェクトにアタッチしたら次のプログラムを記入します。
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; public class CountDownTimer : MonoBehaviour { // 制限時間(分) [SerializeField] private int minute; // 制限時間(秒) [SerializeField] private float seconds; [SerializeField] private Text timerText; // トータル制限時間 private float totalTime; // 前回Update時の秒数 private float oldSeconds; GameManager gameManager; void Start() { totalTime = minute * 60 + seconds; oldSeconds = 0f; gameManager = GameObject.Find("GameManager").GetComponent<GameManager>(); } void Update() { // 制限時間が0秒以下、countDownがfalseなら何もしない if (totalTime <= 0f || !gameManager.countDown) { return; } // 一旦トータルの制限時間を計測; totalTime = minute * 60 + seconds; totalTime -= Time.deltaTime; // 再設定 minute = (int)totalTime / 60; seconds = totalTime - minute * 60; // タイマー表示用UIテキストに時間を表示する if ((int)seconds != (int)oldSeconds) { timerText.text = minute.ToString("00") + ":" + ((int)seconds).ToString("00"); } oldSeconds = seconds; // 制限時間終了 if (totalTime <= 0f) { gameManager.GameOver(); } } }
※上記プログラムは「Unityで経過時間、制限時間を表示する機能を作成する | Unityを使った3Dゲームの作り方(かめくめ)」を参考にさせていただきました。
プログラムができたら、Timerオブジェクトのインスペクタを開いて下の図のようにTextコンポーネントを登録してください。
GameManager.csの変更
最後に、またしても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始まり) [System.NonSerialized] public bool countDown = false; [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; LoadComponents(); } //シーンのロード時に実行(最初は実行されない) void OnSceneLoaded(Scene scene, LoadSceneMode mode) { countDown = false; LoadComponents(); } //コンポーネントの取得 void LoadComponents() { //タイトル画面じゃないなら取得 if(SceneManager.GetActiveScene().name != stageName[0]) { character = GameObject.FindGameObjectWithTag("Player").GetComponent<ThirdPersonCharacter>(); playerRigidbody = GameObject.FindGameObjectWithTag("Player").GetComponent<Rigidbody>(); freeLookCam = GameObject.Find("FreeLookCameraRig").GetComponent<FreeLookCam>(); } } //次のステージに進む処理 public void NextStage() { countDown = false; int maxStageNum = stageName.Length - 1; currentStageNum += 1; //最後のステージの場合、タイトルに戻る if (currentStageNum > maxStageNum) { currentStageNum = 0; } //コルーチンを実行 StartCoroutine(WaitForLoadScene(currentStageNum)); } //任意のステージに移動する処理 public void MoveToStage(int stageNum) { currentStageNum = stageNum; //コルーチンを実行 StartCoroutine(WaitForLoadScene(stageNum)); } //シーンの読み込みと待機を行うコルーチン IEnumerator WaitForLoadScene(int stageNum) { //タイトル画面じゃないならキャラを停止 if (SceneManager.GetActiveScene().name != stageName[0]) { 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() { countDown = false; //キャラやカメラの移動を停止させる 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); } //ゲーム終了 public void ExitGame() { Application.Quit(); } //操作方法とタイトル表示の切り替え public void SwitchTitle(bool isTitle) { Canvas titleCanvas = GameObject.Find("Title Canvas").GetComponent<Canvas>(); Canvas howtoCanvas = GameObject.Find("HowtoPlay Canvas").GetComponent<Canvas>(); if (isTitle) { titleCanvas.enabled = true; howtoCanvas.enabled = false; } else { titleCanvas.enabled = false; howtoCanvas.enabled = true; } } }
カウントダウン用のフラグを追加しました。CountDownTimerではこのフラグを見て、ゲームオーバー中やステージクリア時ならタイマーを止めるようにします。
テストプレイしてカウントダウンが行われれば成功です!
次のページ→動く障害物を作る