Unity3d 协同程序倒计时时间非常慢

Unity3d 协同程序倒计时时间非常慢,unity3d,time,countdown,coroutine,Unity3d,Time,Countdown,Coroutine,嘿,伙计们,作为免责声明,我对编程比较陌生,所以如果我犯了一些非常明显的错误,请对我宽容一些 所以我正在尝试为我的游戏创建一个更高的可定制倒计时计时器,我希望它能够精确到0.01秒。我决定使用协程方法来创建计时器,而不是我见过几次的delta time方法,我认为这是一种更有效的方法。我的游戏不是很密集,因此很容易每秒运行数百帧,所以我认为使用Waitforseconds(0.01)会更好,因为它只需要每秒调用100次,而不是数百次。然而,我的计时器出现了一个大问题。它非常慢。我在谷歌和我的电脑

嘿,伙计们,作为免责声明,我对编程比较陌生,所以如果我犯了一些非常明显的错误,请对我宽容一些

所以我正在尝试为我的游戏创建一个更高的可定制倒计时计时器,我希望它能够精确到0.01秒。我决定使用协程方法来创建计时器,而不是我见过几次的delta time方法,我认为这是一种更有效的方法。我的游戏不是很密集,因此很容易每秒运行数百帧,所以我认为使用Waitforseconds(0.01)会更好,因为它只需要每秒调用100次,而不是数百次。然而,我的计时器出现了一个大问题。它非常慢。我在谷歌和我的电脑上同时运行倒计时,从25秒开始,它比我的倒计时快了10秒。我甚至尝试添加一个人为延迟,认为waitforseconds函数超出了范围,所以我会让时间缩短0.01秒,但结果有点不一致。这是我的密码

using System.Collections;
 using System.Collections.Generic;
 using UnityEngine;
 using UnityEngine.UI;
 public class TimerScript : MonoBehaviour
 {
   public Text textDisplay;
   private double secondsLeft = 30;
   public bool takingAway = false;
 
    private string Texttodisplay;
    
 
    public int Milisecondsdigits = 2;
   void Start()
   {
       textDisplay = GetComponent<Text>();
       Texttodisplay = "00:" + secondsLeft;
       
       if(Milisecondsdigits == 0)
       {
           Milisecondsdigits = -1;
       }
   }
 
     void Update()
     {
         if (takingAway == false && secondsLeft > 0)
         {
             StopAllCoroutines();
             StartCoroutine(TimerTake());
         }
         
         if(Texttodisplay.Length > 8 - (Mathf.Abs(Milisecondsdigits -2)))
         {
             Texttodisplay = Texttodisplay.Substring(0,8- (Mathf.Abs(Milisecondsdigits -2)));
         }
 
         textDisplay.text = Texttodisplay;
     }
 
     IEnumerator TimerTake()
     {
         takingAway = true;
         yield return new WaitForSeconds(0.01f);
         secondsLeft -= 0.01;
         if(secondsLeft < 10)
         {
             Texttodisplay = "00:0" + secondsLeft;
 
         }
         
 
         else 
         {
              Texttodisplay = "00:" + secondsLeft;
 
         }
 
         takingAway = false;
     }
 
 }
使用系统集合;
使用System.Collections.Generic;
使用UnityEngine;
使用UnityEngine.UI;
公共类TimerScript:MonoBehavior
{
公共文本显示;
专用双秒SLEFT=30;
公共布尔塔金加韦=假;
私有字符串文本显示;
公共整数毫秒秒数字=2;
void Start()
{
textDisplay=GetComponent();
Texttodisplay=“00:”+secondsLeft;
如果(毫秒数字==0)
{
毫秒数字=-1;
}
}
无效更新()
{
如果(takingAway==false&&secondsLeft>0)
{
StopAllCoroutines();
start例程(TimerTake());
}
如果(Texttodisplay.Length>8-(Mathf.Abs(毫秒数字-2)))
{
Texttodisplay=Texttodisplay.Substring(0,8-(Mathf.Abs(毫秒数字-2));
}
textDisplay.text=Texttodisplay;
}
IEnumerator TimerTake()
{
takingAway=真;
收益率返回新WaitForSeconds(0.01f);
第二个SLEFT-=0.01;
如果(秒英尺<10)
{
Texttodisplay=“00:0”+秒英尺;
}
其他的
{
Texttodisplay=“00:”+secondsLeft;
}
takingAway=假;
}
}

有人能告诉我如何使这变得更准确,或者为什么它目前表现得极不准确:/

在Unity事件周期中的某个定义点触发WaitForSeconds之类的协同路由事件,该事件在Update()处理后发生(请参阅 )。此定义的执行点可能与计时器延迟不完全一致。这意味着它可能比您希望的等待时间更长

在您的示例中,您告诉它等待0.01秒。假设您正在以每秒30帧的速度运行游戏。每秒30帧的帧时间为1/30秒,约为0.0333秒。WaitForSeconds随后将等待下一帧,0.0333秒将持续到下一帧。然后在下一个WaitForSeconds事件周期中,它会看到延迟已经过去并触发,但实际上由于事件周期之间的延迟,您需要等待的时间超过了3次。由于您的代码假定WaitForSeconds只等待了0.01秒,因此最终等待的时间将比预期的长。在很多应用程序中,这通常并不重要,但当累积频繁的短延迟时,它肯定会起作用

要解决此问题,您有两个选择:

  • 使用Update()中的time.deltaTime手动累积时间

    协同路由可能会在一个特定的环境中检查每帧的完成状态 在
    yield WaitForSeconds
    事件中的类似方式。如果协同程序 检查他们是否需要继续每一帧,使用 Time.deltaTime的效率可能不会比 协同程序。您必须通过基准测试才能找到答案,因为协同程序更高效并不是一个安全的假设

  • 使用Time.Time(或Time.realtimeSinceStartup,如果您希望它不标度)测量WaitForSeconds触发后经过的实际时间跨度,并将其用作从剩余时间中减去的时间

    这里还有一个额外的考虑,如果你想要 文本显示以特定的定期更新,您需要 动态调整传入WaitForSeconds的值 补偿它的漂移


  • 您是否尝试在固定更新中不受腐蚀地执行此操作?修复了默认情况下每0.02秒刷新一次更新,但您可以在“编辑>设置>时间>固定时间步”中将设置为在0.01秒内运行。 用FixedUpdate中的函数替换腐蚀剂 有一个链接可以更好地解释FixeUpdate的工作原理。

    这确实是错误的方法。开始一个合作项目是不免费的,你会开始很多合作项目。您确实应该考虑只使用Delta时间和处理更新中的计算。