この記事でのバージョン
Unity 6000.3.4f1
UniTask 2.5.5
はじめに
UnityはTask(.NETの機能)を使えば「1秒待機」みたいな処理を簡単に実装出来ます。
public async Task SampleMethod() { /*なにか処理1*/ //1秒待機 await Task.Delay(TimeSpan.FromSeconds(1.0)); /*なにか処理2*/ }
それと同じ事をUniTaskというパッケージでも簡単に実装出来ます。
public async UniTask SampleMethod() { /*なにか処理1*/ //1秒待機 await UniTask.Delay(TimeSpan.FromSeconds(1.0f)); /*なにか処理2*/ }
上記のコードは同じように見えて場合によっては挙動が変わってしまうというのが今回の話。
timeScaleの影響
というのも、Task.DelayはTime.timeScaleの影響を受けないですが、
UniTask.DelayはデフォルトではtimeScaleの影響を受けます。
例えばTime.timeScaleを0.5fにして全体の時間の流れを半分(スロー)にした場合、
Taskでは待つ時間は変わりませんが、UniTaskだと待つ時間も倍になります。
//全体の時間の流れを半分(スロー)に Time.timeScale = 0.5f;
//1秒待機(変わらず) await Task.Delay(TimeSpan.FromSeconds(1.0));
//2秒待機(待機時間もスローに) await UniTask.Delay(TimeSpan.FromSeconds(1.0f));
なお、UniTaskは引数でTime.timeScaleの影響を受けないようにも出来るので、
基本UniTaskを使えばOKという感じです。
//Time.timeScaleの影響を受ける(引数なしと同じ設定) await UniTask.Delay(TimeSpan.FromSeconds(1.0f), DelayType.DeltaTime); //Time.timeScaleの影響を受けない await UniTask.Delay(TimeSpan.FromSeconds(1.0f), DelayType.UnscaledDeltaTime); //Time.timeScaleの影響を受けず、実時間ベースで待機 await UniTask.Delay(TimeSpan.FromSeconds(1.0f), DelayType.Realtime);
ちなみにUnscaledDeltaTimeとRealtimeの違いは以下の通りで、
- UnscaledDeltaTime : Time.timeScaleを無視した、フレームごとの経過時間で待つ
- Realtime : Time.timeScaleを無視した、現実の経過時間で待つ
timeScaleに影響されないというの共通ですが、
Realtimeはさらにフレームが更新されなくても時間が進んでると判定されるという感じで、
例えば、ゲームがバックグラウンドにいってる間もカウントが進みます。
(バックグラウンド中に待機が完了するのではなく、戻ってきた時に一気に時間が進むというイメージ)