协程倒数计时器非常慢

问题描述

伙计们,作为免责声明,我是编程的新手,所以如果我犯了一些非常明显的错误,请对我轻松一点

因此,我试图为我的游戏创建一个更高的可自定义倒数计时器,我希望它能够精确到0.01秒。我决定使用Coroutine方法创建计时器,而不是使用几次见过的增量时间计时器,并认为这将是一种更有效的方法。我的游戏不是很密集,因此每秒可以轻松运行数百帧,因此我认为使用Waitforseconds(0.01)会更好,因为每秒只需要调用100次,而不是数百次。但是,我的计时器遇到了主要问题。非常慢。我在Google和我的系统上并排运行了倒数计时器,从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;
     }
 
 }

请让我知道如何使它变得更准确,或者为什么它目前的行为非常不准确:/

解决方法

诸如WaitForSeconds之类的协程事件在Unity事件周期的定义点触发,该事件在处理Update()之后发生(请参见 https://docs.unity3d.com/Manual/ExecutionOrder.html)。此定义的执行点可能与计时器延迟不完全一致。这意味着它可能等待的时间比您想要的要长。

在您的示例中,您告诉它等待0.01秒。假设您以每秒30帧的速度运行游戏。每秒30帧的帧时间为1/30秒,或大约0.0333秒。然后,WaitForSeconds将等待下一帧,并经过0.0333秒,直到下一帧。然后,在下一个WaitForSeconds事件周期中,将看到延迟已经过去并触发,但是由于事件周期之间存在延迟,因此实际上您实际上等待了3倍以上。由于您的代码假定WaitForSeconds仅等待了0.01秒,因此最终等待的时间将超出您的预期。在许多应用程序中,这通常无关紧要,但是在频繁出现短暂延迟的情况下,确实可以。

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

  1. 使用Update()中的Time.deltaTime手动累积时间。

    协程员可能会在一帧中检查每帧的完成状态 yield WaitForSeconds事件中也是如此。如果协程 检查是否需要继续每一帧,使用 Time.deltaTime的效率可能不会比 协程。您必须进行基准测试才能找到答案,因为协程效率更高并不是一个安全的假设。

  2. 使用Time.time(如果不希望缩放,则使用Time.realtimeSinceStartup)来测量WaitForSeconds触发后经过的实际时间跨度,并将其用作从剩余时间中减去的时间。

    这里还需要考虑其他一些因素,如果您希望 文本显示会定期更新,您需要 动态调整您传递给WaitForSeconds的值 补偿其漂移。

,

您是否尝试在固定更新中不使用Corroutine来执行此操作?固定更新默认情况下每0.02秒刷新一次,但您可以在“编辑”>“设置”>“时间”>“固定时间步长”中设置为在0.01秒内运行。 用FixedUpdate中的函数替换该例程 有一个链接可以更好地说明fixedupdate的工作方式。 FixedUpdate Unity