(:3[kanのメモ帳]

個人ゲーム開発者kan.kikuchiのメモ的技術ブログ。月木更新でUnity関連がメイン。

unscaledDeltaTimeとunscaledTimeはtimeScaleだけでなく、ウィンドウがActiveかどうかにも影響されない【Unity】


このエントリーをはてなブックマークに追加

この記事でのバージョン
Unity 2017.4.2f2


はじめに

UnityにはtimeScaleに影響されない時間、unscaledDeltaTimeとunscaledTimeというものがあります。



実はこの二つの値、ウィンドウがActiveかどうかにも影響されないというのが今回の話。


ウィンドウがActiveかどうかにも影響されない

「ウィンドウがActiveかどうかにも影響されない」だけだと分かりにくいので、

例えば以下のように各値を表示し続けたとします。


f:id:kan_kikuchi:20180521120502g:plain


これをPC(Mac)上で動かし、一時的に非アクティブ(違うアプリを選択)して戻すと、

unscaled系だけ値が飛びます。


f:id:kan_kikuchi:20180521121602g:plain
f:id:kan_kikuchi:20180521121649j:plain
f:id:kan_kikuchi:20180521121659j:plain


エディタ上でも一時停止をする事で同様の現象が確認出来ます。


f:id:kan_kikuchi:20180521121737g:plain
f:id:kan_kikuchi:20180521121716j:plain
f:id:kan_kikuchi:20180521121727j:plain


ようは、ウィンドウが非アクティブ時の時間もunscaled系は考慮してしまい、

ウィンドウが非アクティブからアクティブに戻った時に

一気に時間が進んだような感じになってしまうという事です。


例えばtimeScaleを0にしてゲームの一時停止を行い、

UIのアニメーション等、一時停止中にも動作させたいものをunscaled系を使って実装してしまうと、

ウィンドウが非ActiveからActiveに戻った時に

高速でアニメが再生されたり、瞬間移動してしまったりします。


対処法

これに対する一番簡単な対処法はRun In Backgroundを有効にするという事です。


f:id:kan_kikuchi:20180521122727j:plain


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で一時停止しないようにするというのも有効です。