この記事でのバージョン
Unity 2017.4.2f2
はじめに
UnityにはtimeScaleに影響されない時間、unscaledDeltaTimeとunscaledTimeというものがあります。
実はこの二つの値、ウィンドウがActiveかどうかにも影響されないというのが今回の話。
ウィンドウがActiveかどうかにも影響されない
「ウィンドウがActiveかどうかにも影響されない」だけだと分かりにくいので、
例えば以下のように各値を表示し続けたとします。
これをPC(Mac)上で動かし、一時的に非アクティブ(違うアプリを選択)して戻すと、
unscaled系だけ値が飛びます。
エディタ上でも一時停止をする事で同様の現象が確認出来ます。
ようは、ウィンドウが非アクティブ時の時間もunscaled系は考慮してしまい、
ウィンドウが非アクティブからアクティブに戻った時に
一気に時間が進んだような感じになってしまうという事です。
例えばtimeScaleを0にしてゲームの一時停止を行い、
UIのアニメーション等、一時停止中にも動作させたいものをunscaled系を使って実装してしまうと、
ウィンドウが非ActiveからActiveに戻った時に
高速でアニメが再生されたり、瞬間移動してしまったりします。
対処法
これに対する一番簡単な対処法はRun In Backgroundを有効にするという事です。
Run In Backgroundを有効にすると非アクティブになってもアプリが動作し続けるので、
unscaled系の時間が飛ぶという事がなくなります。
他にもunscaled系をラップするためのクラスを作り、
あまりに値が大きい場合は調整するという方法も考えられます。
public static class TimeUtility{ public static float UnscaledDeltaTime { get { float unscaledDeltaTime = Time.unscaledDeltaTime; //あまりにも時間が大きい場合は1フレームを返すように if (unscaledDeltaTime >= 0.1f) { return 1f / 60f; } return unscaledDeltaTime; } } }
//Time.unscaledDeltaTimeを直接使わず、TimeUtility.UnscaledDeltaTimeを使うように
transform.position = transform.position + Vector3.forward * TimeUtility.UnscaledDeltaTime;
もしくはunscaledDeltaTimeを一切使わず、deltaTimeを使うようにする、
と言うよりtimeScaleで一時停止しないようにするというのも有効です。