コンテンツへスキップ

【Unity】制限時間(カウントアップとカウントダウン)を設定する方法

この記事では、ゲームに制限時間を設ける方法を紹介します。カウントダウンを採用するゲームが多いと思いますが、カウントアップにも対応した内容となっています。

作るもの(完成形)

Timer のインスペクター「Is Count Down」にチェックを入れるとカウントダウンに、チェックを外すとカウントアップになるようにします。制限時間を設けない場合は、「Time Limit」を「0」に設定します。

ゲームオブジェクトの概要

構成(ヒエラルキー)

今回必要となるゲームオブジェクトは下図の赤枠部分です。

unity-time-limit1

■ UI:キャンバス
 ボタンやタイマーの表示などの土台

■ Timer:キャンバス
 タイマーの土台

■ Image:画像
 時間を表示する部分の背景

■ DisplayTime:TextMeshPro
 時間を表示するためのテキスト

■ YouLose:TextMeshPro
 「You Lose」を表示するためのテキスト

シーン上のゲームオブジェクト

ゲームオブジェクトは、下図のようにシーン上に配置します。

unity-time-limit0

ゲームオブジェクトの詳細

UI(キャンバス)

unity-time-limit3

■ You Lose:
 ゲームオーバーになったときに表示するテキストです。

■ Timer Obj:
 TimerController で計算している残り時間(表示する時間)を取得するために必要です。

■ Timer Text Obj:
 残り時間を表示するためのテキストです。

Timer(キャンバス)

unity-time-limit4

■ Is Count Down:
チェックあり:カウントダウン
チェックなし:カウントアップ

■ Time Limit:
 制限時間(秒)です。「0」にすると、カウントダウンもカウントアップもしません。

■ Ui Obj:
 タイムオーバーになったときに、UIController に負けたことを通知するために必要です(Dead メソッドの呼び出し)。

■ Player Obj:
 タイムオーバーになったときに、プレイヤーの状態を Dead にするために必要です。

Image(画像)

unity-time-limit5

■ ソース画像:
 残り時間を表示するテキストの背景の画像です。

DisplayTime(TextMeshPro)

unity-time-limit6

■ DisplayTime:
 残り時間を表示するためのテキストです。

YouLose(TextMeshPro)

unity-time-limit8

■ テキスト:
 ゲーム画面に「You Lose」と表示するためのテキストです。

プログラム

プログラムの流れ

UIController は Start メソッドの中で、制限時間を画面に表示するかしないか、TimerController の TimeLimit の値を見に行きます。

TimerController の Update メソッドの中で経過時間を取得し、残り時間を計算します。制限時間を超えたら、TimeOver メソッドが実行され、UIController および PlayerController の Dead メソッドを呼び出して、プレイヤーが負けたことを通知します。

unity-time-limit50

プログラムの中身

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 にします。

以上で、「制限時間(カウントアップとカウントダウン)を設定する方法」の解説を終わります。

広告

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA