UnityでTime.timeが非常に大きくなるとどうなりますか?


37

ここで言われているように

時間

このフレームの開始時刻(読み取り専用)。これは、ゲームの開始からの秒数です。

そして、私が知っているように、時間はフロートに保存されます。したがって、私の質問は、時間の価値が非常に大きくなったときに何が起こるかということです。あふれますか?精度が失われ、バグが発生しますか?ゲームはただクラッシュするのでしょうか?


6
コンテキストについては、最長ビデオゲームマラソンのギネス世界記録をご覧ください。
-Theraot

5
@AlexandreVaillancourt「Time.timeが非常に大きくなると問題はありますか?」と解釈した場合、ここに役に立つ質問があると思います。文字通り「オーバーフロー」だけに焦点を合わせるのとは対照的に。フィードバックに対処するために、これらの行に沿って質問を編集しました。
DMGregory

2
@DMGregoryしかし、質問はすでに回答され、受け入れられています...あなたの編集が少し便利な質問になっていることに同意します。
MichaelHouse

私は、受け入れられた答えがまだ編集されたバージョンに対する正しい答えであるように、編集を表現しようとしました。(結局、それはすでに精度の問題について話している)しかし、それがロールバックされたとしても、私は攻撃をしないでしょう。
DMGregory

回答:


62

単精度のfloatを使用すると、時間の精度が失われる危険があります。

97日間、精度は最も近い秒まで維持されます。しかし、ゲームでは、フレームの長さのオーダーの精度を重視することがよくあります。

秒単位の単精度浮動小数点値は、約9時間後にミリ秒の精度を失い始めます。

これは、すでに1回のプレイセッションの可能性の範囲外ではありません。また、仕事や学校にいるときや寝ているときにゲームを「AFK」のままにしておくこともできます。(これは、ゲームをテストする一般的な方法が、夜間に実行し、午前中にまだ正しく再生されることを確認することである理由の1つです)

完全にシャットダウンするのではなく、プレイセッション間でゲームが中断および再開されることが多い現代のコンソールでは、ゲームの目から見た「シングルセッション」が短いバーストでプレイされても9時間を超えることは予想外ではありません。

Unity deltaTimeが別の答えのPeterの実験によって裏付けられたより高精度の時間ソースから計算されると仮定するとdeltaTime、フレームスケールタイミングに依存することは比較的安全です(deltaTime値を合計することで非常に長い期間を累積することに注意してください-大きな浮動小数点数は、精通したアルゴリズムで補正する場合でも、精度が低下する典型的なレシピです)。

fixedDeltaTimeフレームごとに動的に変更するのではなく、設定した値と同じ値を保持するため、FixedUpdateにタイミング依存の動作を設定して、一貫性をより強力に保証することもできます。deltaTimeこれらのメソッドで適切な固定デルタを自動的に返します。固定更新とフレーム更新の間にビート周波数が存在する可能性がありますが、補間によりこれを滑らかにすることができます

避けたいのは、あるタイムスタンプを別のタイムスタンプから差し引くことで期間を計算することです。数時間のプレイの後、これは壊滅的なキャンセルを引き起こす可能性があり、実行の初期に得られるよりもはるかに精度が低くなります。システムでタイムスタンプの比較が重要な場合は、のSystem.Diagnostics.Stopwatch代わりに他の方法を使用して、独自の高解像度の時間値を生成できますTime.time


アンリアルはまた、コード設計図の両方で、ゲーム時間を単精度浮動小数点数として公開することを選択します。タイムスタンプをリアルタイムで使用して、Unityで行うのと同じように、独自の時間拡張を行うことで回避できます。(Unrealのタイムスタンプタイプは32ビットエポックに基づいていることに注意してください)。必要に応じて、UnrealのC#に拡張機能が存在します。
DMGregory

[ms]の場合、16 484-32 768バンド前後で精度が失われ始めます。つまり、4h30min後に精度を失う可能性があり、9h後には確実に信頼できなくなります。
xmedeko

技術的には4.5〜9時間で、精度は0.98ミリ秒以内です-エラーが1.00ミリ秒を超えるポイントにフラグを付けることにしました。しかし、ポイントは十分に考慮されています-精度は途中で低下するため、より高い精度を必要とするコードはさらに早く誤動作し始める可能性があります。
DMGregory

16

floatの最大値は3.40282347 * 10 ^ 38です。これは、秒単位で測定した場合は10 ^ 31年(ミリ秒単位で測定した場合は10 ^ 28年)です。私を信じて、それはあふれません。

表示される唯一のものは不正確です。ただし、単精度浮動小数点数の精度は10進数7〜8桁です。秒を測定するために使用する場合、約194日間正確です。ミリ秒単位で測定する場合、正確な時間はわずか4,5時間です。そのため、必要な精度に完全に依存しており、ミリ秒までの精度を必要とする場合は、別の方法を見つける必要があります(おそらくそうではありません)。


7
Wolfram Alphaは、言及する価値があるかもしれない何年であるかのトーン設定のアイデアを提供します:それは宇宙の現在の年齢よりおよそ20等級高いです。20 倍ではありませんが、現在の年齢に20を加えたゼロです。
-doppelgreener

1
@ Draco18s UnityがdeltaTimeを測定する方法に依存しますが、各フレームの時点を取り、それらの2つを減算する場合、答えは確かにyesであると思います。
ルークG

7
この答えはまったく正しくありません。実験を実行できます。ループ内でフロートを1つずつインクリメントできます。10 000 000に達すると、インクリメントが停止します。その理由は、floatを扱っているときに、小さな数字を大きな数字に正しく追加できないからです。正しい答えは@DMGregoryによって与えられました
シーガル

2
@Seagull増分についてはどこにも書いていません。実は、フロートで表現できる最大数は(約)3,4 * 10 ^ 38であるため、厳密な意味でのオーバーフローは除外されます(OPの意味)。私は答えがスタンドのように間違っている理由がわかりませんか?
LukeG

2
@Seagull LukeGの答えは(編集が改善される前であっても)正しいと思います。彼の答えと私の答えは、さまざまなクラスのニーズを指しているだけです。フロートの精度とケースの制限について説明するのが好きですが、LukeGは厳密な精度のニーズをあまり重視せずに、この問題をもう少し広く見ていきます。
DMGregory

12

ゲームにはどれくらいの精度が必要ですか?

32ビットの浮動小数点の精度は24ビットです。つまり、時刻tでの精度は±2 -23 ×tです。(これは正確には正確ではありませんが、近いため、正確な詳細はそれほど面白くありません。)

  • 1msの精度が必要な場合、1ms÷2 -23 = 8400 s = 2h 20mの後、32ビットの浮動小数点数は受け入れられなくなります。ほとんどのゲームでは1msの精度は必要ありませんが、音楽アプリケーションでは必要と考えられています。

  • ゲームが144 Hzモニターで実行され、フレーム精度のグラフィックが必要な場合、1÷144 Hz÷2 -23 = 58000 s = 16hの後に、32ビットの浮動小数点数は受け入れられなくなります。16hはゲームを実行するのに長い時間ですが、考えられないことではありません。私たちのかなりの割合が、一回のストレッチで16時間ゲームを実行したことは間違いないでしょう。その時点で、アニメーションと物理の更新は144Hz未満に削減されます。

Unity Time.deltaTimeが高精度のクロックから計算される場合、それを使用しても完全な精度を得ることができます。これが本当かどうかはわかりません。

サイドノート

Windowsのゲームやその他のプログラムはGetTickCount()、時間を把握するためによく使用します。32ミリ秒の整数を使用してミリ秒をカウントするため、コンピューターを長時間放置した場合、約50日ごとにラップします。多くのゲームは、50日間の時点でプレイしていた場合、奇妙な方法でハング、クラッシュ、または不正な動作をすると思われます。

Windowsのような整数にGetTickCount()はオーバーフローのリスクがありますが、UnityのようなフロートにはTime.time精度が失われるリスクがあります。


10

他の答えは推測に過ぎないため、単純なUnityプロジェクトを作成し、しばらく実行させました。数時間後、これが結果です:

  • UnityEngine.Time.timeかなり早く精度を失います。予想どおり、ゲームを4時間実行した後、値は1ミリ秒ジャンプし、その後不正確さが増加します。
  • UnityEngine.Time.deltaTimeUnityが何時間も実行された後でも、最初のミリ秒未満の精度を維持します。したがってdeltaTime、プラットフォームに依存する高解像度カウンター(通常は10〜1000年後にオーバーフローする)から派生することが実質的に保証され ます。deltaTime一部のプラットフォームでは、依然として精度を失う小さなリスクが残っています。

時間の不正確さは、依存するすべての問題ですUnityEngine.Time.time。特定の例の1つは、回転(例:風車の回転)UnityEngine.Mathf.Sin(UnityEngine.Time.time*rotationSpeed)です。これは通常、に基づいています。さらに多くの問題は_Time、シェーダーによってアニメーションに明示的に使用されることです。気づき始める前に、不正確さはどれほど高い必要がありますか?20〜30ミリ秒の精度(2日間)は、問題を認識し、細心の注意を払っている人々が気付くポイントです。50〜100ミリ秒(5〜10日)で、問題を知らない敏感な人が問題を理解し始めます。200〜300ミリ秒(20〜30日)から、問題は明らかです。

これまでのところ、私はの精度をテストしていない_SinTime_CosTimeUnity_DeltaTime私はこれらについてコメントすることはできませんので、。

これは、テストに使用したスクリプトです。UI.Text要素にアタッチされ、プロジェクトのプレーヤー設定により、プロジェクトはバックグラウンドで実行でき、品質設定のVSyncは毎秒Vブランクに設定されます。

public class Time : UnityEngine.MonoBehaviour {
    void Start () {
        LastTime = (double)UnityEngine.Time.time;
        StartTime =  System.DateTime.Now;
        LastPrintTime =  System.DateTime.Now;
    }
    double LastTime;
    System.DateTime StartTime;
    System.DateTime LastPrintTime;
    void Update () {
        double deltaTimeError = (double)UnityEngine.Time.deltaTime - ((double)UnityEngine.Time.time - LastTime);
        if (System.DateTime.Now - LastPrintTime  > System.TimeSpan.FromMilliseconds(1000))
        {
            GetComponent<UnityEngine.UI.Text>().text = "StartTime: " + StartTime.ToLongTimeString()
                + "\nCurrentTime: " + System.DateTime.Now.ToLongTimeString()
                + "\n\nTime.deltaTime: " + UnityEngine.Time.deltaTime.ToString("0.000000")
                + "\nTime.time - LastTime: " + ((float)(UnityEngine.Time.time - LastTime)).ToString("0.000000")
                + "\nAbsolute Error: " +  System.Math.Abs(deltaTimeError).ToString("0.000E0");
            LastPrintTime = System.DateTime.Now;
        }
        LastTime = UnityEngine.Time.time;       
    }
}

ここに画像の説明を入力してくださいここに画像の説明を入力してくださいここに画像の説明を入力してください ここに画像の説明を入力してください

あなたが0.033203値について疑問に思っているなら、私は0.033203125それが実際にであると確信しています。これはのバイナリ浮動小数点表現を持ってい00111101000010000000000000000000ます。0仮数部の多くのに注意してください。

回避策

ほとんどのジャンルは回避策を必要としません。ほとんどのプレイヤーは合計100時間もゲームをプレイしません。したがって、問題を解決するためにお金を投資することは、数日間の連続したプレイタイムが経済的に現実的でない場合にのみ気付くでしょう。残念ながら、重大な欠点を伴わずに問題全体を修正する単純な普遍的な回避策は思いつきません。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.