MRが楽しい

MRやVRについて学習したことを書き残す

Unityでシーンの再生時間の速度を早くしたりゆっくりにする その4(タイムスケール変更時のUpdateとFixedUpdateの動作の違い)

本日は Unity の小ネタ枠です。
今回はTimeScaleを使ってシーンの再生速度を変えた時のUpdateとFixedUpdateの動作の違いについてです。

前回記事

前回記事の続きです。
シーンの再生速度を変更する方法については以下の記事を参照ください。
bluebirdofoz.hatenablog.com

タイムスケール変更時のUpdateとFixedUpdateの動作の違い

実時間の実行間隔についてUpdateはTimeScaleの変更の影響を受けず、FixedUpdateはTimeScaleの変更の影響を受けます。
docs.unity3d.com

動作確認

実際に以下のテストスクリプトを作成して経過時間を計測してみます。
・UnscaledTimeTest2.cs

using UnityEngine;

public class UnscaledTimeTest2 : MonoBehaviour
{
    [SerializeField]
    private float setTimeScale = 1.0f;

    private void Start()
    {
        // タイムスケールを変更する
        Time.timeScale = setTimeScale;
    }

    void Update()
    {
        Debug.Log($"Update : " +
                  $"Time.deltaTime: {Time.deltaTime}, " +
                  $"Time.unscaledDeltaTime: {Time.unscaledDeltaTime}");
    }

    void FixedUpdate()
    {
        Debug.Log($"FixedUpdate : " +
                  $"Time.deltaTime: {Time.deltaTime}, " +
                  $"Time.unscaledDeltaTime: {Time.unscaledDeltaTime}");
    }
}

それぞれTimeScaleの値を変更してUpdateとFixedUpdateの実行間隔を確認しました。
以下の通り、FixedUpdateはTimeScaleの影響を受けて実時間の実行間隔が変化します。

TimeScale 1.0 の場合

Update:ゲーム内の経過時間 0.002 秒、現実の経過時間 0.002 秒
FixedUpdate:ゲーム内の経過時間 0.2 秒、現実の経過時間 0.2 秒


TimeScale 0.25 の場合

Update:ゲーム内の経過時間 0.0005 秒、現実の経過時間 0.002 秒
FixedUpdate:ゲーム内の経過時間 0.2 秒、現実の経過時間 0.8 秒


FixedUpdateの実行間隔を調整する

このため、TimeScaleの値を変更するときにフレームあたりのFixedUpdateコールバックの数を一定に保ちたい場合はFixedUpdateの実行間隔を調整する必要があります。
Time.fixedDeltaTimeを変更してFixedUpdateの実行間隔を変更できます。
docs.unity3d.com

テストスクリプトをTimeScaleの値に合わせてTime.fixedDeltaTimeを変更するように修正しました。
・UnscaledTimeTest3.cs

using UnityEngine;

public class UnscaledTimeTest3 : MonoBehaviour
{
    [SerializeField]
    private float setTimeScale = 1.0f;

    private void Start()
    {
        // タイムスケールを変更する
        Time.timeScale = setTimeScale;

        // タイムスケールに合わせてFixedUpdateの実行時間(ゲーム内時間)を変更する
        Time.fixedDeltaTime = 0.02f * setTimeScale;
    }

    void Update()
    {
        Debug.Log($"Update : " +
                  $"Time.deltaTime: {Time.deltaTime}, " +
                  $"Time.unscaledDeltaTime: {Time.unscaledDeltaTime}");
    }

    void FixedUpdate()
    {
        Debug.Log($"FixedUpdate : " +
                  $"Time.deltaTime: {Time.deltaTime}, " +
                  $"Time.unscaledDeltaTime: {Time.unscaledDeltaTime}");
    }
}

以下の通り、TimeScaleを変更しても実時間の実行間隔が一定になりました。

TimeScale 0.25 の場合

Update:ゲーム内の経過時間 0.0005 秒、現実の経過時間 0.002 秒
FixedUpdate:ゲーム内の経過時間 0.05 秒、現実の経過時間 0.2 秒