さて、UnityのTime.deltaTimeを使っていて、ふと、あれ?おかしくない?と思った事があったのでまとめてみたいと思います。
Time.deltaTimeとは
Time.deltaTimeは「最後のフレームからの経過時間(秒)」と解説される場合が多いです。
そのため、経過時間を図ったり、前回のフレームからの時間による変化などの計算によく使われます。
このような特性から、物理演算の計算をする為に、FixedUpdate内で使われることもあります。
ちなみに、Time.fixedDeltaTimeというものもあるのですが、FixedUpdate内でTime.deltaTimeを使用するとTime.fixedDeltaTimeと同じ値になります。その為、どちらを使っても結果は一緒になります。
あれ?おかしくないですか?最後のフレームからの経過時間であるのなら、Time.fixedDeltaTimeと同じになる場合は限られます。
1フレーム内にFixedUpdateが1回呼ばれていた場合はわかります。しかしながら、FixedUpdateは1フレーム内に0回の時もあれば、複数回呼ばれる時もあります。
FixedUpdateの詳しい仕様をご存じない方は↓の記事を参考にしてください。
さて、もし、FixedUpdateが呼ばれた回数が1回以外の場合、次のフレームでのFixedUpdate内のTime.deltaTimeはTime.fixedDeltaTimeと一致しないはずです。
FixedTimeStepはデフォルトで0.02ですから、
FixedUpdate (Time.deltaTime 0.02, Time.fixedDeltaTime 0.02)
↓
FixedUpdate (Time.deltaTime 0.02, Time.fixedDeltaTime 0.02)
↓
Update
↓
FixedUpdate (Time.deltaTime 0.04, Time.fixedDeltaTime 0.02) ←こうなってほしい
※ゲーム内時間を進めるのがFixedUpdateの前であるため
しかしながら、実際にやってみると、最後の部分は
FixedUpdate (Time.deltaTime 0.02, Time.fixedDeltaTime 0.02)
となります。
いろいろ試してみた結果、どのような状態であったとしても、FixedUpdate内で呼び出したTime.deltaTimeはTime.fixedDeltaTimeと一致しました。
あるぇ~?実は最後のフレームからの経過時間ではないのでは・・・?
と思いましたが、公式のリファレンスを見たらちゃんと説明されていました。
正確なTime.deltaTimeの説明
Time.deltaTimeの公式のリファレンスを読んでいたら
MonoBehaviour.FixedUpdate uses fixedDeltaTime instead of deltaTime.
と書いてありました。
FixedUpdate内ではTime.deltaTimeの代わりにTime.fixedDeltaTimeが使用されますよということみたいです。
つまり、Time.deltaTimeは
通常時は最後のフレームからの経過時間だが、FixedUpdate内で呼ばれる場合のみ、ゲーム内時間を進める秒数に仕様が変わる
ということみたいですね。
あと、もっと詳しく言うと
処理落ちして、最後のフレームからの経過時間がMaximum Allowed Timestepを超えた場合、Time.deltaTimeは実際の経過時間ではなくMaximum Allowed Timestepと同じ値になります。
この場合でもFixedUpdate内ではTime.deltaTimeはTime.fixedDeltaTimeと同じになります。
よくよく調べて見ると「最後のフレームからの経過時間」と解説されているサイトさんではTime.deltaTimeをFixedUpdateでは使っていないみたいです。そのため、「あれ?説明おかしくない?」と思ったのは自分の早合点というか、解説されている方々の想定外の使い方をしてしまっていたということみたいです。
じゃぁ、だからなんだ?という話ですが、Unityが自動でTime.deltaTimeの中身を入れ替えてくれているので、私たちは、特に意識せずにUpdateだろうが、FixedUpdateだろうが、時間を使った計算ができるというわけですね。
※Update内ではUpdate→Update間の経過時間になり、FixedUpdate内ではFixedUpdate→FixedUpdate間の経過時間に自動で変更される為
逆に言うと、FixedUpdate内のTime.deltaTimeは最後のフレームからの経過時間ではないので、そう思って使用すると違う結果が返ってきてしまいます。ご注意ください。