【问题标题】: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) 或您选择的任何时间。上面的评论是对的,问题的格式是:stackoverflow.com/help/minimal-reproducible-example
  • 谢谢@Absinthe

标签: c# unity3d coroutine


【解决方案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】:

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

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

  2. 它会阻止整个代码继续运行,直到时间结束,这意味着即使我们在关闭循环之前等待(设置 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 中提到他们的名字
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-09-22
  • 1970-01-01
  • 2015-07-14
相关资源
最近更新 更多