【時よ止まれ】スマホ向けUnity 時間の概念 | 最高のゲームを、最高の仲間と作って、最高のお客様に遊んでほしいと思う人の相棒のブログ

最高のゲームを、最高の仲間と作って、最高のお客様に遊んでほしいと思う人の相棒のブログ

スマホアプリ開発における技術等を公開していきます。
忘備録として、勉強として、不定期に投稿します。
たまに、趣味や生活のことも。

■時間は一つじゃない
こんにち(ばん)は。
菅原だ。

今回はUnityの時間の概念について調べてみた。
なぜ調べたかというと、今作っているゲームに一時停止を実装したかったからだ。
Unityには二つの時間の概念が存在する。
これらを利用して、一時停止を実現した。


■UnityEngine.Time
一つ目はTime系だ。
これは「アプリ内時間」として表現できる。

代表的なのは「Time.deltaTime」だろうか。
Time.deltaTimeは「前フレームと現フレームとの時間の差分(秒)」が格納されている。
可変フレームレートを想定したアプリでは定番。
スマホ向けのアプリの場合は、機種により処理速度がマチマチな為、特に利用頻度が多いだろう。
処理速度に関係なく一定の時間に一定の距離を動かす為に必要だ。


private float mAdd = 0.0f;
void Update () {
// 良い例(処理速度に関係なく一定な移動を実現)
mAdd += 1.0f * Time.deltaTime;

// 駄目な例(高フレームレートな機種ほど移動距離が大きくなってしまう)
mAdd += 1.0f;
}



ちなみにFixedUpdate内では、Time.deltaTimeを掛けなくても良い。
FixedUpdateがフレームとは別の概念で動作しているからだ。

その他にもTime系は色々な場面で利用されている。
例えばPhisics関連や、アニメーション関連や、パーティクルや、コルーチンも。
iTweenもTime系の時間を利用している。
なので、Timeの時間を止めれば、これらすべての動作を一時停止させることが出来るのだ。
時間を止める鍵は、「Time.timeScale」だ。


Time.timeScale = 1.0f; // 通常の時間の進み方
Time.timeScale = 0.5f; // 半分の時間の進み方(つまりスローモーションとなる)
Time.timeScale = 0.0f; // 時間が止まる


Time.timeScaleを0にすることで一時停止が実現できた。
元に戻すには、Time.timeScaleを1にすればよい。
Time系は色々な場面で使えるので一度マニュアルに目を通しておくことをお勧めする。

Unity公式ドキュメントのUnityEngine.Timeに関するページ
http://docs-jp.unity3d.com/Documentation/ScriptReference/Time.html


また、FixedUpdateを利用する際の設定をするページも紹介しておく。
Unity公式ドキュメントのタイムマネージャに関するページ
http://docs-jp.unity3d.com/Documentation/Components/class-TimeManager.html





■System.DateTime
二つ目はDateTime系だ。
これは「現実時間」として表現できる。
現在の日付や時刻を取得する場合に利用することが多いだろう。


DateTime.Now.Year; // 西暦年
DateTime.Now.Month; // 月
DateTime.Now.Day; // 日
DateTime.Now.Hour; // 時
DateTime.Now.Minute; // 分
DateTime.Now.Second; // 秒
DateTime.Now.Millisecond; // ミリ秒


見ての通りnamespaceが「System」なので、Unity外部のライブラリを利用している。
なので、DateTimeに関する詳細はこちらのページを案内させて頂く。
http://msdn.microsoft.com/ja-jp/library/system.datetime





■Timerクラスを作る
さてさて、実は最初に紹介させて頂いたUnityEngine.Timeで一時停止した場合に、私のアプリでは問題が発生してしまった。
一時停止中にはアニメーションするメニュー操作を行っていたのだが、これらのGUIも動かなくなってしまったのだ。
そこで、System.DateTimeを使った簡単な時間管理クラスと、Tweenerクラスを作って一時停止中でもアニメーションを実現させた。
ここでは、System.DateTimeを使った時間管理クラスを紹介しておく。


/******************************************************************************/
/*!
@file MNZTimer.cs
@brief 時間管理クラス
@date 作成日(2014/08/07)
@author 作成者名 monolizm LLC
@par Copyright
Copyright (c) 2014年 monolizm. All rights reserved.
@par 履歴
- 2014/08/07
- 初版
******************************************************************************/
using UnityEngine;
using System.Collections;
using System;


// ----------------------------------------------------------------------------
/*! @class MNZTimer
@brief 時間管理クラス
*/
// ----------------------------------------------------------------------------
public class MNZTimer : MonoBehaviour {

protected double m_nSec = 0; //!< アプリ起動からの経過時間(秒)
protected double m_nDeltaTime = 0; //!< 前フレームとの差分時間(秒)
protected static MNZTimer m_Instance; //!< インスタンス

private DateTime m_nStartTime; //!< アプリ起動時の時刻を記録する

// ----------------------------------------------------------------------------
/*!
@brief このクラスのインスタンスを取得(未生成なら生成)
@return インスタンス
*/
// ----------------------------------------------------------------------------
public static MNZTimer Instance {
get {
if(m_Instance == null) {
m_Instance = (MNZTimer)FindObjectOfType(typeof(MNZTimer));
if (m_Instance == null) {
Debug.LogError("MNZTimer:Instance Error[m_Instance == null]");
}
}
return m_Instance;
}
}


// ----------------------------------------------------------------------------
/*!
@brief アプリ起動からの経過時間(秒)を取得
@return アプリ起動からの経過時間(秒)
*/
// ----------------------------------------------------------------------------
public double sec {
get {
return m_nSec;
}
}


// ----------------------------------------------------------------------------
/*!
@brief 前フレームとの差分時間(秒)を取得
@return 前フレームとの差分時間(秒)
*/
// ----------------------------------------------------------------------------
public double deltaTime {
get {
return m_nDeltaTime;
}
}


// ----------------------------------------------------------------------------
// Use this for initialization
// ----------------------------------------------------------------------------
void Start () {
m_nStartTime = DateTime.Now;
m_nDeltaTime = 0;
}


// ----------------------------------------------------------------------------
// Update is called once per frame
// ----------------------------------------------------------------------------
void Update () {
// 前フレームの時間を記録
double nLastSec = m_nSec;

// 起動時からの経過時間を計算
m_nSec = (DateTime.Now - m_nStartTime).TotalSeconds;

// 前フレームとの差分を求める
m_nDeltaTime = m_nSec - nLastSec;
}

}



使い方は、GameObjectに紐付けて、

MNZTimer.Instance.sec
MNZTimer.Instance.deltaTime

を利用シーンに合わせて呼ぶだけ。
Time.timeScaleに影響を受けない時間管理を行うことが出来る。






モノリズム
http://monolizm.com

Facebook
https://www.facebook.com/monolizm

Twitter
https://twitter.com/monolizm

相棒のブログ
http://ameblo.jp/nd-crown