0

I am using a float to calculate and display the time the player has left (in seconds) to finish the game.

In my game time sometimes goes faster, so the time left value needs to go big.

Here's my problem: I use the following code in Update:

  Update () {
            timeleft -= Time.deltaTime;
            Debug.Log (timeleft);
            counter.text = "Time Left = " +timeleft.ToString("F0");
    }

At game start, the time left value is set to a really high number (32 million, about a year in seconds).

The rate at which the time drops varies in the game, so I am using a float with time.deltaTime.

Unity stores this big initial value as 3.2E+07. As soon as that happens, my counter.text doesn't work properly anymore, as that just waits until the next scientific notation value comes up. So it looks like the timer text is stuck, while in the back it is in fact still counting down. Hope I'm making sense here. For the avoidance of doubt: the counter display works fine for values below 1 million.

How do I fix this problem? How do I convert timeleft.ToString so that it displays the correct value?

As per the comments below, someone suggested to use a decimal instead. That won't work with deltaTime as that needs a float or I misunderstood where and how to use the decimal.

I tried to create a new int and use Mathf.RoundToInt on the float, but that doesnt work: the timer stays stuck at the larger value.

Killbert
  • 171
  • 1
  • 4
  • 16
  • 1
    use a [decimal](https://stackoverflow.com/q/618535/578411) instead of float? – rene Sep 23 '17 at 08:24
  • I've tried the same scenario and i can see the value well in my scene. But in the inspector it says 1e+07. Changed the float to decimal as @rene said. It works well. – Thalthanas Sep 23 '17 at 08:28
  • Possible duplicate of [Double to string conversion without scientific notation](https://stackoverflow.com/questions/1546113/double-to-string-conversion-without-scientific-notation) – FCin Sep 23 '17 at 08:48
  • Edited the original question. The suggested duplicate question is not applicable or at least unclear to me as a solution. – Killbert Sep 23 '17 at 12:56
  • try ; **(decimal)Time.deltaTime** @Killbert – Thalthanas Sep 23 '17 at 13:45

1 Answers1

2

The short moral here is that floating-point arithmetic doesn't conform to ordinary human intuitions about numbers.

You write:

Unity stores this big initial value as 3.2E+07. As soon as that happens, my counter.text doesn't work properly anymore, as that just waits until the next scientific notation value comes up. So it looks like the timer text is stuck, while in the back it is in fact still counting down.

This is incorrect: it's not just the text that's not changing, the number itself isn't changing for small values of Time.deltaTime. The problem is that the precision of float reduces as the value gets larger. Moreover, since the underlying storage format is binary floating-point, the 'gap' between the next-largest and next-smallest number is difficult to intuit.

You can test this yourself with the following code:

float f = 3.2e7f;
string s1 = f.ToString();
Console.WriteLine(s1);
string s2 = f.ToString("F0");
Console.WriteLine(s2);
string s3 = (f - 7).ToString("F0");

var f2 = f;
for (int i = 0; i < 3000000; i++)
{
    f2 = f2 - 1f;
}
var diff = f - f2;
Debug.Log(diff);
if (f2 == f) 
{
    Debug.Log("Floating point numbers are strange.");
}

The value of f2 never changes, despite being supposedly decremented 3 million times. This is because 3.2e7f - 1f is exactly equal to 3.2e7f.

The solution, as pointed out in the comments, is to use decimal, which uses a base-10 format and conforms much better to human intuitions. This will count down correctly.

  decimal timeLeft = 3.2e7M;
  Update () {
            timeleft -= (decimal)Time.deltaTime;
            Debug.Log (timeleft);
            counter.text = "Time Left = " +timeleft.ToString("F0");
}
David Oliver
  • 2,251
  • 12
  • 12
  • Tried that, But if I do that, Unity gives me this error: Cannot implicitly convert type `decimal' to `float'. An explicit conversion exists (are you missing a cast?) – Killbert Sep 24 '17 at 07:15
  • 1
    Ah, my bad, the error came from somewhere else. Your solution works like a charm. Thanks for the lesson in Human intuition ;-) – Killbert Sep 24 '17 at 07:50