いろんなゲームにタイマーは付き物です。タイムアップを知らせるためや、ラップタイムを計測するためのタイマーなど用途は様々。ここではいろんなタイマーを作りながら、UnityやC#の要素を覚えて行きましょう。
いろんなタイマーを知る、タイマーの種類
まずは作るためのタイマーの種類を上げていき、それぞれの特徴を抑えて行きます。
ストップウォッチ型
1つ目はストップウォッチのようなもの。数字がカウントアップしながらどのぐらい時間が経過したかを知ることができるもの。機能としては
- スタートボタンを押すと計測開始
- ストップボタンで一時停止
- リセットボタンで0秒からやり直し(停止)
カウントダウン式
マリオみたいなステージクリア式のゲームによくある制限時間などで利用されるタイプ。エヴァの活動限界などでも利用されるのと似ていますね。
下図サンプルはテキストに残り時間を表示するフォーマットを変えていますがスクリプトは同じものを使っています。
画像を使ったタイマー表現
3つ目は画像を使ったタイマーの表現。画像ファイルが必要ですが、下図のように一周するまでの状態を可視化したり、残り時間のバーが消えていくような表現をすることが出来ます。フラグの設定によって増えるパターンや減るパターンいずれにも対応出来ます。
タイマーのメイン処理
先程の3つのパターンはいずれも共通のタイマー処理を行うプログラムを利用しています。しかも内容自体は全然大したことをしていません。
このあと作成する3つのタイマーはいずれもここで作成するGameTimerスクリプトが必要になります。空のゲームオブジェクトに貼り付けてご利用下さい。
スクリプト
タイマーの処理は以下のスクリプトで動いています。メソッドがいくつかありますが、ストップウォッチ方式での開始・停止処理を行わせるものがほとんどです。もう少し丁寧に作れる部分もありますが、今回は外部から参照されやすい現在の時間と各メソッドをpublicにしました。実装方法としてはシングルトンで作る方が便利ですが、今回はインスタンスとして扱うようにしました。
using UnityEngine;
public class GameTimer : MonoBehaviour
{
private float m_fTimer;
public float CurrentTime { get { return m_fTimer; } }
public bool m_bActive = false;
private void Update()
{
if (m_bActive)
{
m_fTimer += Time.deltaTime;
}
}
public void OnStart()
{
m_bActive = true;
}
public void OnStop()
{
m_bActive = false;
}
public void OnReset()
{
m_fTimer = 0f;
OnStop();
}
}
インスペクターでの設定など
GameTimerスクリプトはシーン内に空のゲームオブジェクトを作成してGameTimerスクリプトを貼り付けて下さい。インスペクターにはActive用のフラグのOn/Offを指定することが出来ます。こちらはストップウォッチではチェックを外した状態で、それ以外チェックを入れておくのがおすすめです。
インスペクターで数字の変化を確認したい場合はm_fTimerをpublicに変更することでインスペクターで確認出来ます
ストップウォッチの作り方
ストップウォッチの作り方ですが、ポイントになるのは以下の2点
- UIのボタンとGameTimerのメソッドの連携を行う部分
- タイマーの数字を表示するための文字列操作
スクリプト自体はシンプルなので、ストップウォッチでGameTimerとの連携部分に慣れて他のタイマー作成時に迷わないようにしておきましょう。
スクリプト
スクリプトではアップデートでひたすら経過時間の表示を行っています。表示形式を合わせるためにあれこれやっています。
using UnityEngine;
using UnityEngine.UI;
public class ShowTimerText : MonoBehaviour
{
public Text m_txtTimer;
public GameTimer m_gameTimer;
private void Update()
{
m_txtTimer.text = string.Format("{0:D2}:{1:D2}:{2:D2}",
(int)m_gameTimer.CurrentTime / 60,
(int)m_gameTimer.CurrentTime % 60,
(int)(m_gameTimer.CurrentTime * 100) % 60
);
}
}
シーン・インスペクターの設定
主に2つの設定を行います。一つは経過時間表示用のテキスト、もう一つは各3種類のボタン。
テキストの用意とコンポーネントのアタッチ
テキストはUI>Textから追加をして下さい。Unity2021以降の場合はLegacy内のテキスト。テキストのフォントサイズなどは再生時に見やすくなる大きさに調整を行います。
テキストの準備が出来たらShowTimerTextスクリプトをアタッチします。アタッチ先は今作ったテキストのGameObjectでもいいし、新たに空のゲームオブジェクトを準備してもOK。インスペクターの設定は以下
項目 | セットするもの |
---|---|
Txt Timer | 今作成したテキストのゲームオブジェクト |
Game Timer | GameTimerスクリプトが張り付いたゲームオブジェクト。 ない場合は空のゲームオブジェクトを用意して貼り付けて下さい。 |
ボタン類の準備・設定
ボタンは3つ必要になります。各ボタンに共通するのはOnClickにイベントを追加してNone(Object)部分にGameTimerスクリプトが張り付いたゲームオブジェクトを指定して下さい。呼び出すメソッドは以下
ボタン | メソッド |
---|---|
スタートボタン | GameTimer.OnStart |
一時停止ボタン | GameTimer.OnStop |
リセットボタン | GameTimer.OnReset |
動作確認
ゲームを動かしてみると、スタートボタンでタイマーが動き出して、一時停止やリセットを行うことが出来ます。
カウントダウンタイマーの作り方
GameTimerは数字が増えていくだけですが、使い方を変えると減らしていくような使い方も可能です。GameTimerは一切変更しませんが表示側の対応で作ることが出来ます。
スクリプト
カウントダウンは表示の種類を複数持たせられるようにしました。素の状態で表示させてみたり、エヴァーみたいに0詰めしてみたり、内部的には少数まであるけれど表示には整数部分のみを表示してみたりしてます。カラクリの核になる部分はString.Formatです!
using UnityEngine;
using UnityEngine.UI;
[RequireComponent(typeof(Text))]
public class ShowCountdown : MonoBehaviour
{
public float m_fStartTime;
public string m_strFormat;
public GameTimer m_gameTimer;
private Text m_txt;
private void Start()
{
m_txt = GetComponent<Text>();
}
private void Update()
{
float fShowTime = Mathf.Clamp(m_fStartTime - m_gameTimer.CurrentTime, 0f, m_fStartTime);
m_txt.text = string.Format(m_strFormat, fShowTime);
}
}
RequireComponentに注意!
今回のスクリプトはRequireComponentがあります。これはRequireComponent(typeof(ここに入るコンポーネント))のここに入るコンポーネントを同インスペクター内に要求する命令です。今回の場合だとStartメソッドでお構い無しでGetComponent<Text>していますが、RequireComponentのおかげで成功することが保証されます。
インスペクターでの設定
インスペクターの設定を行う前に表示するテキストを用意して下さい。サンプルのようにしたい場合は3つのテキストが必要になります。
共通で設定する部分
各テキストにShowCountdownスクリプトをアタッチします。3つ設定する場所がありますが、以下で説明
項目 | 設定するもの |
---|---|
FStart Time | 何秒からカウントダウンするか 1で1秒 ここも個別に設定可能ですが、今回はすべて同じ値にしておきましょう |
Str Format | ここにテキストで表示したいフォーマットを指定 String.Formatに指定されます。 |
Game Timer | GameTimerスクリプトが張り付いたゲームオブジェクトをセット |
個別に設定を行うところ
表示する文字のフォーマットを変更する部分は変えていきましょう。詳しくカスタマイズしたい場合は「C# string format」で検索するといろんな形式を指定することが出来ます。ここでは次のような3パターンを指定します。
表示サンプル | 指定するフォーマット(Str Format) |
---|---|
123.45678 | {0} |
123.45 | {0:0.00} |
123 | {0:000} |
同じような形式で表示したい場合、上記以外のパターンでのフォーマットもあります。覚えやすいフォーマットを見つけてみましょう!
動作確認
動かしてみるとこんな感じになります。タイマーが動き出さない場合はGameTimerのインスペクターからbActiveフラグをOnにしましょう
画像を使ったタイマーの作り方
最後は画像を使ったタイマーの作り方。作成するに当たりなんでもいいので画像を用意して下さい。ない場合はここの画像をダウンロードしてもOKです。
スクリプト
先程のカウントダウンとの一番の違いは、増える方と減る方の両方に対応している点です。m_bIncrementalフラグのTrue/Falseで増えるのと減るのを指定することが出来ます。
using UnityEngine;
using UnityEngine.UI;
public class ShowImageTimer : MonoBehaviour
{
public GameTimer m_gameTimer;
public Image m_imgTarget;
public float m_fTargetTime;
public bool m_bIncremental = true;
void Update()
{
if (m_bIncremental)
{
m_imgTarget.fillAmount = m_gameTimer.CurrentTime / m_fTargetTime;
}
else
{
m_imgTarget.fillAmount = (m_fTargetTime - m_gameTimer.CurrentTime) / m_fTargetTime;
}
}
}
インスペクターの設定
主に設定するのはShwoImageTimerと表示されるImageになります。
円形に表示される画像(Image)
円形に表示されるイメージの設定は以下。画像は好きなので大丈夫ですが、Image Type以降の設定はSource Imageに画像ファイルをセットしていないと指定が出来ません。(画像ファイルが必要な理由)Fill Amountはなんとなく0にしてますが、0~1の間を動かすと虫食い状態が見られると思います。
四角く横から減ってく画像(Image)
SourceImageは丸い画像でも大丈夫です。ImageType以降の設定を変えることで左から減ったり右から減ったりします。
ShowImageTimerの設定
ShowImageTimerは空のGameObjectでもImageでもどちらでも大丈夫なので貼り付けておけばOK。Img Targetに変更したい画像のGameObjectをセットすれば制御出来ます。
GameTimer | おなじみGameTimerの張り付いたGameObject |
Img Target | 上で設定した画像(Image)のGameObject |
F Target Time | タイマーの完了するまでの所要時間 下図は10秒 |
B Incremental | True : 画像が徐々に見えてくる False : 画像がどんどん消えていく |
動作確認
こんな感じにタイマーが表現できていればOK!
コメント