ここまででゲームの基本的な流れができました。しかし、このままでは単にユニティちゃんを走らせるだけのゲームになってしまい単調なので、これからゲーム的な部分を作り込んでいく必要があります。今回はステージに制限時間を設けて緊張感が出るようにしてみましょう。
タイマーオブジェクトとタイマー用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ではこのフラグを見て、ゲームオーバー中やステージクリア時ならタイマーを止めるようにします。
テストプレイしてカウントダウンが行われれば成功です!
次のページ→動く障害物を作る


