この記事では、ゲームに制限時間を設ける方法を紹介します。カウントダウンを採用するゲームが多いと思いますが、カウントアップにも対応した内容となっています。
目次
作るもの(完成形)
Timer のインスペクター「Is Count Down」にチェックを入れるとカウントダウンに、チェックを外すとカウントアップになるようにします。制限時間を設けない場合は、「Time Limit」を「0」に設定します。
ゲームオブジェクトの概要
構成(ヒエラルキー)
今回必要となるゲームオブジェクトは下図の赤枠部分です。
■ UI:キャンバス
ボタンやタイマーの表示などの土台
■ Timer:キャンバス
タイマーの土台
■ Image:画像
時間を表示する部分の背景
■ DisplayTime:TextMeshPro
時間を表示するためのテキスト
■ YouLose:TextMeshPro
「You Lose」を表示するためのテキスト
シーン上のゲームオブジェクト
ゲームオブジェクトは、下図のようにシーン上に配置します。
ゲームオブジェクトの詳細
UI(キャンバス)
■ You Lose:
ゲームオーバーになったときに表示するテキストです。
■ Timer Obj:
TimerController で計算している残り時間(表示する時間)を取得するために必要です。
■ Timer Text Obj:
残り時間を表示するためのテキストです。
Timer(キャンバス)
■ Is Count Down:
チェックあり:カウントダウン
チェックなし:カウントアップ
■ Time Limit:
制限時間(秒)です。「0」にすると、カウントダウンもカウントアップもしません。
■ Ui Obj:
タイムオーバーになったときに、UIController に負けたことを通知するために必要です(Dead メソッドの呼び出し)。
■ Player Obj:
タイムオーバーになったときに、プレイヤーの状態を Dead にするために必要です。
Image(画像)
■ ソース画像:
残り時間を表示するテキストの背景の画像です。
DisplayTime(TextMeshPro)
■ DisplayTime:
残り時間を表示するためのテキストです。
YouLose(TextMeshPro)
■ テキスト:
ゲーム画面に「You Lose」と表示するためのテキストです。
プログラム
プログラムの流れ
UIController は Start メソッドの中で、制限時間を画面に表示するかしないか、TimerController の TimeLimit の値を見に行きます。
TimerController の Update メソッドの中で経過時間を取得し、残り時間を計算します。制限時間を超えたら、TimeOver メソッドが実行され、UIController および PlayerController の Dead メソッドを呼び出して、プレイヤーが負けたことを通知します。
プログラムの中身
TimerController.cs
using UnityEngine;
public class TimerController : MonoBehaviour
{
public bool IsCountDown = false;
public float TimeLimit;
[SerializeField] private GameObject UiObj;
private UIController uiController;
[SerializeField] private GameObject playerObj;
private PlayerController playerController;
[System.NonSerialized] public float DisplayTime;
private bool isTimeOver = false;
private float nowTime;
private void Start()
{
nowTime = 0;
if (IsCountDown)
{
DisplayTime = TimeLimit;
}
else
{
DisplayTime = 0;
}
uiController = UiObj.GetComponent<UIController>();
playerController = playerObj.GetComponent<PlayerController>();
}
private void Update()
{
if (!isTimeOver)
{
nowTime += Time.deltaTime;
if (IsCountDown)
{
DisplayTime = TimeLimit - nowTime;
if (DisplayTime < 0)
{
DisplayTime = 0;
TimeOver();
}
}
else
{
DisplayTime = nowTime;
if (TimeLimit < DisplayTime)
{
DisplayTime = TimeLimit;
TimeOver();
}
}
}
}
private void TimeOver()
{
uiController.Dead();
playerController.Dead();
}
}
■ 19 ~ 26 行目:
「IsCountDown」にチェックが入っていればカウントダウン。変数 DisplayTime に TimeLimit の値を代入します。
カウントアップの時は、「0」を代入します。
■ 36 行目:
経過時間(nowTime)を求めています。
■ 39 行目:
カウントダウンのときは、表示する時間は「残り時間(※)」です。
※ 制限時間 – 経過時間
■ 48 行目:
カウントアップの時は、表示する時間は「経過時間」です。
■ 58 行目:
TimeOver メソッドの中で、UIController と PlayerController の Dead メソッドを呼び出します。
UIController.cs
using TMPro;
using UnityEngine;
using UnityEngine.SceneManagement;
public class UIController : MonoBehaviour
{
[SerializeField] private GameObject youLose;
[SerializeField] private GameObject TimerObj;
[SerializeField] private GameObject TimerTextObj;
private TimerController timerController;
private void Start()
{
if (TimerObj != null)
{
timerController = TimerObj.GetComponent<TimerController>();
if (timerController.TimeLimit == 0.0f)
{
TimerObj.SetActive(false);
}
}
else
{
TimerObj.SetActive(false);
}
youLose.GetComponent<TextMeshProUGUI>().enabled = false;
}
private void Update()
{
int time = (int)timerController.DisplayTime;
TimerTextObj.GetComponent<TextMeshProUGUI>().text = time.ToString();
}
public void Dead()
{
youLose.GetComponent<TextMeshProUGUI>().enabled = true;
}
}
■ 20 行目:
TimerController の TimeLimit が「0」の場合は、カウントダウンもカウントアップもしません。Timer のオブジェクトを非表示にします。
■ 30 行目:
Update メソッド内では、TimerController から 表示する時間(DisplayTime)を取得し、TimerTextObj にその値を代入します。
■ 36 行目:
Dead メソッドは、制限時間を過ぎると、TimerController から呼び出されます。テキスト「You Lose」を表示します。
PlayerController.cs
using UnityEngine;
public class PlayerController : MonoBehaviour
{
[SerializeField] private GameObject uiObject;
private UIController uiController;
private Animator animator;
private PlayerState nowState = PlayerState.Idle;
private PlayerState oldState = PlayerState.Idle;
private void Start()
{
uiController = uiObject.GetComponent<UIController>();
}
private void FixedUpdate()
{
if (nowState == PlayerState.Dead && oldState != PlayerState.Dead)
{
GetComponent<CapsuleCollider2D>().enabled = false;
rbody2D.AddForce(new Vector2(0, 5), ForceMode2D.Impulse);
animator.Play(PlayerState.Fall.ToString());
oldState = PlayerState.Dead;
}
}
public void Dead()
{
nowState = PlayerState.Dead;
}
}
■ 19 ~ 25 行目:
プレイヤーの状態が Dead になったとき、プレイヤーを少し上に浮かせた後に、ステージの下に落ちていくようにします(負けの演出)。
■ 29 行目:
Dead メソッドは、制限時間を過ぎると、TimerController から呼び出されます。プレイヤーの状態を Dead にします。
以上で、「制限時間(カウントアップとカウントダウン)を設定する方法」の解説を終わります。