【unity】時間経過、カウントダウン、プレイ時間についてfloatを見直す

概要

用途にもよるが安易にfloatで時間の加算をするとどんどんおかしくなる。

実践

時間の計算(カウントダウン)

よく記事で見かける

Time.deltaTime

を使うのはいいとして

using UnityEngine;
using TMPro;

public class TimerCountDown : MonoBehaviour
{
    [SerializeField] float m_CounterMax;
    [SerializeField] float m_Counter;
    [SerializeField] TextMeshProUGUI m_CounterText;
    // Start is called before the first frame update
    void Start()
    {
        m_Counter = m_CounterMax;
    }

    // Update is called once per frame
    void Update()
    {
        m_Counter -= Time.deltaTime; // 減算

        if(m_Counter < 0)
        {
            Debug.Log("終了。");
        }

        m_CounterText.text = ((int)m_Counter).ToString();
    }

}

実行結果

経過時間(プレイ時間)を表示したい場合

同じように実装するのはNG

m_Counter += Time.deltaTime; // 加算

うまく動いているように見えるが

何十時間もプレイ時間をためておく場合にはうまく動かない

例えば20時間=72000秒経過していたとする。

全然おかしい、floatの仮想部23bitでは限界があるのでdoubleを使う必要がある。

時間経過のサンプルコード

using UnityEngine;
using TMPro;

public class TimerCountDown : MonoBehaviour
{
    [SerializeField] double m_CounterMax;
    [SerializeField] double m_Counter;  // double
    [SerializeField] TextMeshProUGUI m_CounterText;
    // Start is called before the first frame update
    void Start()
    {
        m_Counter = m_CounterMax;
    }

    // Update is called once per frame
    void Update()
    {
        m_Counter += Time.deltaTime;
        m_CounterText.text = m_Counter.ToString("F2");
    }

}

期待通りの結果になる。

おわり

時間経過も10時間を超えないならfloatでいいかもしれないが、大体表記は99:99:99や999時間まで表すゲームが多い。

浮動小数点の落とし穴にはまらないようにしよう。

【unity】秒から時、分、秒を計算する。もよければ参考に

こちらのリポジトリーにサンプルのシーンを入れています。

コメント