【Unity】unscaledDeltaTimeとは?timeScaleに影響されずに時間を計測

unscaledDeltaTimeとは? Unity

こんにちは、ともくんのゲーム作り部屋にようこそ!

このページでは、

「unscaledDeltaTimeってなに?」

「timeScaleを無視して時間を計測したい!」

というお悩みの方に向けた内容となっています。

Unityでは、Timeクラスで定義されているtimeScaleを変更することで、ゲーム内の進む時間を変えることができます。

ただ、このtimeScaleを変更した際、deltaTimeを使って時間を計測すると、変更されたゲーム内の時間の速さを基準に計測してしまうことになります。

今回紹介するunscaledDeltaTimeは、timeScaleによる変更の影響を受けず、時間を計測することができる変数です。

そこで、このページでは、Unityで使えるunscaledDeltaTimeについて、どんな変数なのか、また使い方までをまとめていきます。

なお、

Windows11
Unity Hub3.11.0
Unity6

のバージョンで解説しています。

この記事を書いた人

ゲーム作りを学び始めた一児のパパです。
このブログは、子供から「ゲームを作ってみたい!」と言われ、非プログラマーでゲーム作りをしたことない僕が、ゲーム作りの本を読んで独学でゲーム開発を学んでいるブログです。
同じように初めてゲーム作りをしている方と一緒に学んでいけるようなブログに出来たらいいなと思っています。
また、「このコードはおかしい」とか「もっと良い書き方があるよ!」などあれば、どんどん指摘して頂けると助かります。

unscaledDeltaTimeとは?timeScaleの値に影響されずに時間計測

unscaledDeltaTimeとは、timeScaleの値に影響されずにフレーム間の時間を計測することができる変数です。

そもそもtimeScaleというのは、ゲーム内の進む時間を決めている変数で、デフォルトでは「1」となっています。

例えば、このtimeScaleの値を「2」に変更すると、ゲーム内の時間が通常より2倍速く進み、「0.5」に変更したら通常の半分の速度で進むことになります。

また、ゲーム内で指定の時間を計測する際、deltaTimeという変数を使ってフレーム間の時間を計測することができますが、timeScaleを変更した場合は、その変更された速度で時間を計測してしまうことになります。

そこで、timeScaleを変更しても、時間の計測は通常の速度で行いたいという場合に使うのが、unscaledDeltaTimeという変数です。

このunscaledDeltaTimeは、timeScaleの値に影響されることがなく、フレーム間の時間を計測することができる変数となっています。

例えば、ゲーム内でtimeScaleを変更して、スローモーションや時間を停止させるようにした場合に、unscaledDeltaTimeを使うことで、通常と同じ速度で時間計測を行ってゲーム内の処理を作ることができます。

ちなみに、同様にtimeScaleの影響を受けずに、ゲーム開始時からの時間を計測できるunscaledTimeという変数もあります。

unscaledDeltaTimeの使い方

ここからは、unscaledDeltaTimeの使い方について紹介していきます。

Time.unscaledDeltaTimeと記述する

unscaledDeltaTimeは、Timeクラスで定義されている変数で、以下のように記述することで、フレーム間の時間をfloat型で取得することができます。

Time.unscaledDeltaTime

例えば、以下のようにdeltaTimeとunscaledDeltaTimeで、時間を計測して表示させるようにしてみます。

それぞれの変数をフレーム毎に加算するように、以下のスクリプトを作成しておきます。

using TMPro;
using UnityEngine;

public class Test : MonoBehaviour
{
    public TextMeshProUGUI deltaTimeText;
    public TextMeshProUGUI unscaledDeltaTimeText;
    public float _timeScale;
    float _deltaTime;
    float _unscaledDeltaTime;
    bool timerStart = false;

    void Start()
    {
        Time.timeScale = _timeScale;    // timeScaleの値を指定する処理
    }

    void Update()
    {
        if (Input.GetKeyDown(KeyCode.Space) && !timerStart)
        {
            timerStart = true;
        }

        if (timerStart)
        {
            _deltaTime += Time.deltaTime;   // deltaTimeを加算する処理
            deltaTimeText.text = _deltaTime.ToString("F3"); // deltaTimeを表示させる

            _unscaledDeltaTime += Time.unscaledDeltaTime;   // unscaledDeltaTimeを加算する処理
            unscaledDeltaTimeText.text = _unscaledDeltaTime.ToString("F3"); // unscaledDeltaTimeを表示させる
        }
    }
}

15行目で、timeScaleをインスペクターから設定した値が入るように設定しています。

そして、30行目でunscaledDeltaTimeの値を加算する処理を作っていて、31行目でその値を表示させるようにしています。

ちなみに、deltaTimeの値も27,28行目で同様の処理で表示させています。

まず、timeScaleの値をデフォルトである「1」にセットして計測を開始してみると、

deltaTimeもunscaledDeltaTimeも、同じ速度で計測されているのが分かります。

次に、timeScaleの値を半分の「0.5」で開始すると、

deltaTimeは先ほどよりもゆっくり時間が進むようになりましたが、unscaledDeltaTimeは変わらず計測されているのが分かります。

このようにunscaledDeltaTimeは、timeScaleの値を変更しても、計測される時間が変わらないようになります。

ゲームを一定時間2倍の速度にする処理を作る

実際に、unscaledDeltaTimeを使って、ゲームを一定時間の間だけ2倍の速度にする処理を作ってみます。

ここでは、以下のようにオブジェクトが左から右に移動する処理を作り、スペースキーを押したら5秒間速度が2倍となり、その後通常の速度に戻るという処理を作ってみます。

まず、オブジェクトにRigidbodyコンポーネントをアタッチして、以下のスクリプトで移動するようにしています。

using UnityEngine;

public class Test : MonoBehaviour
{
    Rigidbody2D rb;

    void Start()
    {
        rb = GetComponent<Rigidbody2D>();   // Rigidbodyコンポーネントを取得
    }

    void FixedUpdate()
    {
        rb.AddForce(transform.right * 10f); // 右方向に向かって力を加える処理
    }

    void OnBecameInvisible()
    {
        transform.position = new Vector2(-10f, transform.position.y);   // カメラ外になったら左に移動する処理
    }
}

14行目でAddForceメソッドを使って右に移動させる処理を行い、17行目でOnBecameInvisibleメソッドを使って画面から外れたら左に座標を戻してループさせるようにしています。

ちなみに、Rigidbodyコンポーネントは、以下のようにLinear Damping「1」Gravity Scale「0」に設定しています。

次に、時間の速度を変更する処理として、空オブジェクトを作成して以下のスクリプトをアタッチしていきます。

using UnityEngine;

public class TimeController : MonoBehaviour
{
    bool timer = false;
    float _unscaledDeltaTime;

    void Update()
    {
        if (Input.GetKeyDown(KeyCode.Space) && !timer)
        {
            Time.timeScale = 2.0f;  // 2倍の速度にする処理
            timer = true;
        }

        if (timer)
        {
            _unscaledDeltaTime += Time.unscaledDeltaTime;   // unscaledDeltaTimeを加算する処理
            // 5秒間経過した場合
            if (_unscaledDeltaTime >= 5.0f)
            {
                Time.timeScale = 1.0f;  // 速度を戻す処理
                _unscaledDeltaTime = 0f;
                timer = false;
            }
        }
    }
}

スペースキーを押した場合の中の12行目で、timeScaleを「2」に変更する処理を行っています。

そして、bool型の変数を使って2倍の速度になっているかどうかを判定していて、trueの際に18行目でunscaledDeltaTimeを加算させる処理を作っています。

この加算した値が5以上になった場合に、22行目でtimeScaleを「1」に戻す処理を行っています。

これでゲームを実行してみると、

スペースキーを押すと時間の進む速度が2倍となり、通常の速度で5秒経過すると元の速度に戻っているのが分かります。

ちなみに、unscaledDeltaTimeではなくdeltaTimeを使った場合は、

スペースキーを押すと同様に時間の進む速度は速くなりますが、計測時間も速く進むため、上記のように2.5秒程度で元に戻ってしまうことになります。

まとめ

このページでは、Unityで使えるunscaledDeltaTimeについて、どんな変数なのか、また使い方までをまとめていきましたが、いかがでしたでしょうか?

unscaledDeltaTimeとは、timeScaleの値に影響されずにフレーム間の時間を取得してくれる変数です。

例えば、スローモーション中の時間を計測するような場合に、unscaledDeltaTimeを使うことで、通常の速度で時間を計測してくれるようになります。

timeScaleの変更中にdeltaTimeを使うと、想定した時間とは異なるタイミングで処理されることになるため、その際はunscaledDeltaTimeが便利に活用できます。

最後までお読みいただきまして、ありがとうございました!

コメント