一段时间后结束协程函数内循环的最佳方法是啥?

Posted

技术标签:

【中文标题】一段时间后结束协程函数内循环的最佳方法是啥?【英文标题】:What's the best way to end a loop inside a coroutine function after time?一段时间后结束协程函数内循环的最佳方法是什么? 【发布时间】:2021-10-15 18:49:37 【问题描述】:

这是我的第一个问题,我猜一切都很清楚-

协程 (UnityC#) 中的循环行为不正确,或者我做错了什么!检查代码 cmets...

bool loop=true;
bool once=false;   

IEnumerator Fun()

    while (loop)
    
        //those 3 lines must be repeated for the whole 2.5 seconds,am I right! but it only run once so why?
        carRb.drag += .005f;
        Debug.Log("Loop1:"+loop);
        if (!once)          //last rep. line
         
            once = true;
            yield return new WaitForSeconds(2.5f); 
            loop = false;
        
        yield return new WaitForEndOfFrame();
    
    yield return new WaitForSeconds(2f); //will run this line after 2.5s        
    Debug.Log("Loop2: "+loop);      //will run this line and whats below after (2.5+2s) 
    carRb.drag = 25f;
    carController.canControl = false;
    Destroyed = true; 

【问题讨论】:

如果你没有告诉我们你想做什么,我们怎么能告诉你你做错了什么? 请提供minimal reproducible example 清楚地表明您遇到的问题 我试图在 2.5 秒后结束 courotine 中的循环,它仅在 1 帧后结束 欢迎来到 SO。请原谅这里的巨魔,最近似乎有一种文化,即向那些提出合理问题但没有 100% 遵守规则的人发起攻击。要在特定时间后结束循环,您只需要在循环内添加一个计时器变量并添加 2.5 秒。当它达到您的阈值时,循环应该退出。将While (loop) 更改为While (myTimer < 30) 或您选择的任何时间。上面的评论是对的,问题的格式是:***.com/help/minimal-reproducible-example 谢谢@Absinthe 【参考方案1】:

once值为false,进入if条件后等待2.5s结束循环。

bool loop=true;
bool once=false;

IEnumerator Fun()

    float time=0;
    while (loop)
    
        //those 3 lines must be repeated for the whole 2.5 seconds,am I right! but it only run once so why?
        carRb.drag += .005f;
        Debug.Log("Loop1:"+loop);
        yield return null;  // wait each update call
        time+=Time.deltaTime;
        if (time>2.5f)          //last rep. line
        
            once = true;
            loop = false;
        
    
    yield return new WaitForSeconds(2f); //will run this line after 2.5s
    Debug.Log("Loop2: "+loop);      //will run this line and whats below after (2.5+2s)
    carRb.drag = 25f;
    carController.canControl = false;
    Destroyed = true;

【讨论】:

这就是我在编写代码时尝试做的事情,但不幸的是它不是那样工作的,它只运行一次(1 帧)并且 Log 函数只打印一次 你没有提供任何新东西,还是谢谢你 您将在第一次迭代中关闭循环,因此它不会循环多次。等待几秒钟使代码等待 2.5 秒。在此之前它不会执行下一行代码 yield return new WaitForSeconds(2.5f);代码只是坐在那里,什么也不做。在 2.5 之后 sencode loop = false;行执行。所以在下一次迭代中while循环退出 以及它之后的下一行是 loop=false;正在发生,......你说它什么都不做,但它不会阻止它执行后发生的事情,你能解释一下吗?谢谢【参考方案2】:

最清晰的方式解释这里的误解是:

    WaitForSeconds 不能在单独的盒子或类似的东西中工作 所以

    它会阻止整个代码继续运行,直到时间结束,这意味着即使我们在关闭循环之前等待(设置 loop=false),我们仍将处于第一次迭代中。 结束循环的最好方法是使用数值变量,每帧增加它并检查它是否达到我们想要的时间然后中断

感谢@user3315036 和@Absinthe

代码如下:

IEnumerator Fun()
    float time=0;

    while(time<2.5f)
        carRb.drag += .005f;
        Debug.Log("Loop1");
        time+=Time.deltaTime;       
        yield return null;

    
    yield return new WaitForSeconds(2f); //will run this line after 2.5s        
    Debug.Log("2: ");      //will run this line and whats below after (2.5+2s) 
    carRb.drag = 25f;
    carController.canControl = false;
    Destroyed = true; 


【讨论】:

当有人能够在 cmets 中回答您的问题时,通常会要求他们添加答案并接受。 他们的答案不是第一个好的答案,这就是答案:(一次的值为假,所以它进入 if 条件然后等待 2.5 秒并结束循环),他们在讨论后对其进行了编辑,即使在我们不清楚的编辑之后,我也会在 BIG BOLD Title 中提到他们的名字

以上是关于一段时间后结束协程函数内循环的最佳方法是啥?的主要内容,如果未能解决你的问题,请参考以下文章

Laravel 3 - 查询同一天的开始和结束日期的最佳方法是啥

现在 MPMoviePlayerPlaybackDidFinishReasonUserInfoKey 已被弃用,找到播放结束原因的最佳方法是啥?

如何在 Lua 中结束循环协程?

在 MFC 中制定计划的最佳方法是啥

在 iOS 上循环播放一段音频

等到 for 循环内的所有函数调用结束其执行 - Javascript