制限時間のタイマーと開始時のカウントダウンの作り方

前回までの作業でステージを用意することができました。もちろんこのままでも十分楽しめると思いますが、特に制限時間などはないのでゲーム的にはやや緊張感に欠ける気がします。どうせならダレないようにタイマー等を用意してみたいものですね。

そこでここでは

  • 制限時間を設定できるタイマー
  • (ついでに)ステージ開始時のカウントダウン処理

を作ってみましょう。


※ここでご紹介するタイマーやカウントダウン処理の基本的な仕組みは、旧版のユニティちゃんパルクールユニティちゃんの2Dアクションのものと同様ですが、今回のゲーム用に処理を書きなおしてあります。

スポンサーリンク

タイマー&カウントダウン用のUIの作り方

では、まずはタイマーやカウントダウンの数字を表示するためのUIを作ります。くろくま基本アセット2のキャンバスのプレハブ(KurokumaBasicAssets2/Prefabs/UI/Canvasフォルダ内)をヒエラルキーにドラッグ&ドロップして、次のように2か所にテキストを配置してください。

タイマー&カウントダウン用キャンバス

※テキストの文字列は空欄でOKです(上の図では分かりやすいようにダミーテキストを入れてあります)。

できたらこのキャンバスを適当なフォルダにドラッグ&ドロップしてプレハブ化しておきましょう。

タイマーとカウントダウンのC#スクリプト

では次にタイマーとカウントダウンの処理を行うC#スクリプトを書いていきます。新しいC#スクリプトを作り、名前を「TimeManager」にしたら次のコードを書いてください。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class TimeManager : MonoBehaviour
{

  public bool isActive = false;

  [Header("必要なコンポーネントを登録")]
  [SerializeField]
  Text timerText = null;
  [SerializeField]
  Text countdownText = null;

  [Header("時間の設定")]
  [SerializeField]
  int minutes = 0;
  [SerializeField]
  float seconds = 0;

  [Header("カウントダウンの設定")]
  [SerializeField]
  bool countdownEnabled = false;
  [SerializeField]
  float countdownWaitTime = 1.5f;
  [SerializeField]
  AudioClip[] countdownSe = null;
  [SerializeField]
  string goText = "GO!!";

  float currentTime;
  float oldSeconds;
  float totalTime;

  GameManager gameManager;
  SoundManager soundManager;
  KurokumaCharacterController player;

  // 現在の時間を取得できるプロパティ(※今回は未使用)
  public float CurrentTime
  {
    set
    {
      currentTime = value;
      currentTime = Mathf.Max(currentTime, 0);

      if (currentTime > totalTime)
      {
        totalTime = currentTime;
      }
    }
    get
    {
      return currentTime;
    }
  }

  public float TotalTime
  {
    get
    {
      return totalTime;
    }
  }

  public float RemainingTime
  {
    get
    {
      return totalTime - currentTime;
    }
  }

  void Start()
  {
    gameManager = GameObject.FindGameObjectWithTag("GameController").GetComponent<GameManager>();
    soundManager = GameObject.FindGameObjectWithTag("GameController").GetComponent<SoundManager>();
    player = GameObject.FindGameObjectWithTag("Player").GetComponent<KurokumaCharacterController>();

    InitTime();
    StartCoroutine("Countdown");
  }

  void Update()
  {
    Timer();
  }

  public void InitTime()
  {
    oldSeconds = 0;
    totalTime = minutes * 60 + seconds;
    currentTime = totalTime;

    UpdateTimeText();
  }

  // カウントダウンタイマー
  void Timer()
  {
    if (!isActive || currentTime <= 0f)
    {
      return;
    }

    currentTime = minutes * 60 + seconds;
    currentTime -= Time.deltaTime;

    minutes = (int)currentTime / 60;
    seconds = currentTime - minutes * 60;

    if ((int)seconds != (int)oldSeconds)
    {
      UpdateTimeText();
    }

    oldSeconds = seconds;

    if (currentTime <= 0f)
    {
      isActive = false;

      gameManager.GameOver();
    }
  }

  void UpdateTimeText()
  {
    timerText.text = minutes.ToString("D2") + ":" + ((int)seconds).ToString("D2");
  }

  // ステージスタート時のカウントダウン
  IEnumerator Countdown()
  {
    if (!countdownEnabled || countdownSe.Length == 0)
    {
      yield break;
    }

    isActive = false;

    // プレイヤーを動けなくする(=入力を受け付けないようにする)
    player.InputEnabled = false;

    // カウントダウン開始前の待ち時間
    yield return new WaitForSeconds(countdownWaitTime);

    countdownText.enabled = true;

    WaitForSeconds waitOneSec = new WaitForSeconds(1);

    // カウントダウンの音声ファイルの数だけカウント
    for (int i = countdownSe.Length; i >= 1; i--)
    {
      if (i == 1)
      {
        countdownText.text = goText;
      }
      else
      {
        countdownText.text = (i - 1).ToString();
      }

      if (countdownSe[i - 1] != null)
      {
        soundManager.PlaySe(countdownSe[i - 1]);
      }

      yield return waitOneSec;
    }

    isActive = true;

    // プレイヤーを動けるようにする
    player.InputEnabled = true;

    yield return waitOneSec;

    countdownText.enabled = false;
  }

}

C#スクリプトの解説

少し長めですがシンプルなスクリプトなので特に解説することはありません。コード中のコメント等を見ながら処理を読み取って頂ければと思います。

ただカウントダウンの部分だけは少し特殊で、カウントダウンは「予め登録したAudioClipの数」だけ行うようになっているので注意してください。

動作に必要な設定を行う

スクリプトが書けたらタイマー等がちゃんと動くように設定を行っていきます。次の手順で作業を行ってください。

  1. シーンに新しい空のゲームオブジェクトを作り、名前を「TimeManager」にする。
  2. 先ほど作ったキャンバスをTImeManagerオブジェクトの子にする。
  3. TimeManagerオブジェクトに先ほど作ったTimeManagerコンポーネントをアタッチする。
  4. TimeManagerコンポーネントの「Timer Text」「Countdown Text」に、手順2.で設定したキャンバスのテキストを設定する。
  5. TimeManagerオブジェクトをプレハブ化する。
  6. TimeManagerコンポーネントの「Minutes」「Seconds」を変更して制限時間を設定する。

※ステージを複数作ってある場合は、すべてのステージにTimeManagerオブジェクトを配置して制限時間を設定しておいてください。

ユニティちゃんのボイスファイルのインポート

さてここまでできたら動作確認をしたいところですが、その前にまだやることがあります。今回のカウントダウンのスクリプトは先述の通り、登録したサウンドファイルの数だけカウントするようになっているので、例えばカウントダウン時の「3,2,1,スタート!!」という音声を登録する必要があります。

そこでここではユニティちゃんのボイスファイルをインポートしてみます。…といってもボイスファイルは単体では配布されていないようなので、面倒ですが昔のユニティちゃんのモデルに同梱されている音声を使わせていただくことにしましょう。ボイスファイルが含まれているパッケージは下のリンク先から入手できます。

ユニティちゃん 3Dモデルデータ - ダウンロード - UNITY-CHAN! OFFICIAL WEBSITE

ダウンロードしたら「Voice」フォルダだけインポートしましょう。インポートできたらサウンドファイルを下の画像のように登録してください。

ボイスファイルの登録

テストプレイして動作確認してみよう

これでタイマーやカウントダウンの処理が完成したので、ちゃんと動くかどうかを確認してみましょう。再生ボタンを押して次の項目を確認してみてください。

  • ゲームがスタートしたらカウントダウンが始まる
  • カウントダウン中はユニティちゃんを動かせないようになっている
  • カウントダウンが終わったらユニティちゃんが動くようになる
  • 設定した時間通りにタイマーが作動する
  • 制限時間になったらゲームオーバーになる

上記がすべてOKなら成功です。


次のページ→ステージセレクト用シーンの作り方