[英]Using a large float value as a timer in Unity3d
我使用浮动控件来计算和显示玩家完成游戏所需的时间(以秒为单位)。
在我的游戏中,时间有时会更快,因此剩余时间值需要变大。
这是我的问题:我在Update中使用以下代码:
Update () {
timeleft -= Time.deltaTime;
Debug.Log (timeleft);
counter.text = "Time Left = " +timeleft.ToString("F0");
}
在游戏开始时,剩余时间值设置为非常高的值(3200万,大约一年,以秒为单位)。
在游戏中,时间下降的速率会有所不同,因此我使用的是带有time.deltaTime的浮点数。
Unity将这个较大的初始值存储为3.2E + 07。 一旦发生这种情况,我的counter.text就无法正常工作,因为它一直等到下一个科学计数法值出现为止。 因此,它看起来像是计时器文本被卡住了,而实际上在后面却仍在倒计时。 希望我在这里有意义。 为避免疑问:计数器显示适用于低于100万的值。
我该如何解决这个问题? 如何转换timeleft.ToString,使其显示正确的值?
根据下面的评论,有人建议使用小数代替。 这与deltaTime不兼容,因为它需要浮点数,或者我误解了在哪里以及如何使用小数。
我试图创建一个新的int并在浮点数上使用Mathf.RoundToInt,但这没有用:计时器停留在较大的值上。
这里的简短道义是浮点算术不符合人类对数字的一般直觉。
你写:
Unity将这个较大的初始值存储为3.2E + 07。 一旦发生这种情况,我的counter.text就无法正常工作,因为它一直等到下一个科学计数法值出现为止。 因此,它看起来像是计时器文本被卡住了,而实际上在后面却仍在倒计时。
这是不正确的:不只是文本没有变化,对于Time.deltaTime
较小值, 数字本身也没有变化。 问题在于, float
的精度会随着该值变大而降低。 而且,由于基础存储格式是二进制浮点数 ,因此很难理解第二大数字和第二小数字之间的“差距”。
您可以使用以下代码自己对此进行测试:
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.");
}
尽管f2
的值减少了300万次,但其值从未改变。 这是因为3.2e7f - 1f
等于 3.2e7f
。
如评论中所指出的,解决方案是使用decimal
,它使用以10为底的格式,并且更符合人类的直觉。 这将正确倒计时。
decimal timeLeft = 3.2e7M;
Update () {
timeleft -= (decimal)Time.deltaTime;
Debug.Log (timeleft);
counter.text = "Time Left = " +timeleft.ToString("F0");
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.