[Unity] Time.timeとTime.realtimeSinceStartupについてのお話

Unityでモーションを実現したいとき、現在時刻を参照することはよくあると思われます。
現在時刻はTime.timeから分かります。
しかし、このTime.timeはTime.timeScaleの値により時刻の進行速度が変化します。

デフォルトはTime.timeScale=1となっており、本来の速度で時間が経過していきます。

Time.timeScaleの値によらない時刻を取得するには、Time.realtimeSinceStartupを参照します。

したがって、Time.timeScale=1のとき、Time.timeとTime.realtimeSinceStartupは同じ値になると考えられます。
しかし、実際に値を取得すると微妙に異なっていることが分かります。

以下がその検証用スクリプトです。

using UnityEngine;
using System.Collections;

public class TimeTest : MonoBehaviour {

	// Use this for initialization
	void Start () {
	}

	// Update is called once per frame
	void Update () {
		Debug.Log ("Time.time = " + Time.time + " , Time.realtimeSinceStartup = " + Time.realtimeSinceStartup);
	}
}

実際に結果をコンソールに出力してみると、見事に値が異なっていることを確認できます。

Time.time = 6.569162 , Time.realtimeSinceStartup = 6.58668
Time.time = 6.591497 , Time.realtimeSinceStartup = 6.609009
Time.time = 6.593105 , Time.realtimeSinceStartup = 6.610617
Time.time = 6.594737 , Time.realtimeSinceStartup = 6.612248

※2014/12/13 追記
しかし、上記のコードではTime.timeの参照後にTime.realtimeSinceStartupを参照しているので結果として値がずれて当然かと思われます。
試しに以下のように順序を入れ替えて実行してみます。

using UnityEngine;
using System.Collections;

public class TimeTest : MonoBehaviour {

    // Use this for initialization
    void Start() {
    }

    // Update is called once per frame
    void Update() {
        Debug.Log("Time.realtimeSinceStartup = " + Time.realtimeSinceStartup + " , Time.time = " + Time.time);
    }
}
Time.realtimeSinceStartup = 0.6573095 , Time.time = 0.6098088
Time.realtimeSinceStartup = 0.6772348 , Time.time = 0.6300333
Time.realtimeSinceStartup = 0.6972438 , Time.time = 0.6509956
Time.realtimeSinceStartup = 0.7172379 , Time.time = 0.6701386

Time.realtimeSinceStartupを先に参照しているにもかかわらずTime.timeより値が大きくなっています。
両者ともゲーム起動時からの経過時間ですが、Time.realtimeSinceStartupはリアルタイムな時間、Time.timeは現在フレームの開始時における時間となり内容が異なります。
Time.timeがTime.realtimeSinceStartupより小さかったのはこのためです。

同フレームの中で両者を2回ずつ参照してみます。

using UnityEngine;
using System.Collections;

public class TimeTest : MonoBehaviour {

    // Use this for initialization
    void Start() {
    }

    // Update is called once per frame
    void Update() {
        Debug.Log(
            "Time.realtimeSinceStartup:1 = " + Time.realtimeSinceStartup +
            " , Time.realtimeSinceStartup:2 = " + Time.realtimeSinceStartup +
            " , Time.time:1 = " + Time.time +
            " , Time.time:2 = " + Time.time);
    }
}
Time.realtimeSinceStartup:1 = 3.114911 , Time.realtimeSinceStartup:2 = 3.114912 , Time.time:1 = 3.083903 , Time.time:2 = 3.083903
Time.realtimeSinceStartup:1 = 3.131449 , Time.realtimeSinceStartup:2 = 3.13145 , Time.time:1 = 3.100469 , Time.time:2 = 3.100469
Time.realtimeSinceStartup:1 = 3.147841 , Time.realtimeSinceStartup:2 = 3.147842 , Time.time:1 = 3.117036 , Time.time:2 = 3.117036
Time.realtimeSinceStartup:1 = 3.164524 , Time.realtimeSinceStartup:2 = 3.164525 , Time.time:1 = 3.133603 , Time.time:2 = 3.133603

Time.realtimeSinceStartupは同フレームでの1回目と2回目の値が異なりタイマーが進行していることが分かります。
一方でTime.timeは1、2回目とも同じ値です。
同フレーム内ではTime.timeは固定の値となります。

このことからも、両者のタイマー値を混在して使うのはバグの元になると断言できます。
勿論、両者の値の意味を知った上で併用するのは問題ありません。
タイマーを使うときはどちらを使うかを慎重に選ぶ必要があります。
Time.timeとTime.realtimeSinceStartupを同じ意味の値として比較すれば時間が逆戻りしたりして大変なことになります。
(ここで私はド嵌りしました・・・)

今回はタイマーの使用上の注意点ということで挙げておきました。

■参考サイト
Unity – Scripting API: Time.realtimeSinceStartup
Unity – Scripting API: Time.time

COMMENTS & TRACKBACKS

  • Comments ( 2 )
  • Trackbacks ( 0 )
  1. By 匿名

    同時に呼び出してるわけではないので必ずしも同じ値にならないのではないでしょうか

    • By ftvoid

      ご指摘ありがとうございます。
      記事の検証用スクリプトだけでは誤解を招いてしまう内容でしたので、追記しておきました。

      Time.timeとTime.realtimeSinceStartupには厳密に同時にアクセスできないので、アクセス時間のずれが生じます。
      同フレーム内でTime.realtimeSinceStartupに続けざまにアクセスすると時間が進行して値が大きくなります。

      一方、Time.timeは現在フレームが開始したときの時間なので、Time.realtimeSinceStartup→Time.timeの順にアクセスしてもTime.timeのほうが値が小さくなります。
      (Time.timeScaleを変更しなくともTime.timeよりTime.realtimeSinceStartupの方が時間進行している)
      同フレーム内でTime.timeに何回アクセスしても値は変わりません。

      このことについて追記にまとめたので参考にしていただければと思います。