【问题标题】:Am I understanding Coroutines correctly?我是否正确理解协程?
【发布时间】:2020-04-29 02:14:07
【问题描述】:

我正在编写我的第一个 Unity 游戏。我有一系列嵌套函数,我们称它们为 Function1、Function2 等。假设在 Function3 中,我想在短时间内显示一些内容在执行更多代码之前

如果我将 Function3 设为 Coroutine 并以 yield return new WaitForSeconds 退出,这不会阻止我的其他函数中的所有代码执行,而只会阻止 Function3 中其余代码的执行,对吗?与此同时,函数 1 和函数 2 继续愉快地前进。

有没有什么方法可以在不将每个函数重组为协程并放入大量 yield 和 while 语句的情况下获得我想要的东西? (在我的实际游戏中,我想成为协程的函数之前还有很多函数。)

我将添加一些伪代码来说明我的情况。

谢谢。

public Function1()
    {
        .
        .
        Does some stuff
        .
        .
        call Function2()
        .
        .
        Do some more stuff
        .
        .
    }

 public Function2()
 {
    .
    .
    Does some stuff
    .
    .
    StartCoroutine(Function3())
    .
    .
    Does some more stuff
    .
    .
    return to Function2;
 }

IEnumerator Function3()
{
    .
    .
    Does some stuff...
    Now I want to wait for specified time (say, .5 seconds) to display a message, play a sound, etc., **without continuing the code in Function2 or Function1 * *!
    yield return new WaitForSeconds(.5f)
    Then do some more stuff
    .
    .
    return to Function2;
 }

【问题讨论】:

  • 在本站的代码块中编写代码,突出显示代码并按下类似{ }的按钮
  • StartCoroutine 不会暂停其所在函数的执行。如果您想等待协程完成,那么该代码需要进入协程内部函数(或者方法本身需要是协程)。请参阅this answerthis answerthis answer
  • 谢谢。 Draco18 的一个链接将我发送到嵌套协程的链接,这对我有很大帮助。我需要用“yield return StartCoroutine()”调用最后一个例程。这会暂停执行,直到我的计时器例程完成并且滚动完成。

标签: c# unity3d


【解决方案1】:

有多种方法可以做到这一点,但是我更喜欢使用在协程“完成”时调用的回调操作。

public IEnumerator Function1(Action callback)
{
    // do some stuff
    yield return new WaitForSeconds(1);
    // do some stuff
    callback.Invoke();
}

public IEnumerator Function2(Action callback)
{
    // do some stuff
    yield return new WaitForSeconds(1);
    // do some stuff
    callback.Invoke();
}

public void CallingMethod()
{
    StartCoroutine(Function1(() => 
    {
        StartCoroutine(Function2(() =>
        {
            // whatever other code you want executed
        }));
    }));
}

这种方法避免了使用类标志(布尔值),这很容易使您的代码混乱。此外,它还可以让您的方法轻松重用。

【讨论】:

  • 首先,感谢 Scott Chamberlain 帮助我了解如何格式化代码块。我相应地编辑了我的问题(我认为)。不道德:我不认为这会做同样的事情。我不想延迟“上层”功能,只希望最后一个功能。我想暂停执行上层函数中的代码,直到 Function3 中的延迟到期。请记住,Function2 或 3 可能驻留在与 Function1 不同的脚本中。
  • 有没有办法通过在 Update() 中放一些东西来做到这一点?例如,如果我有一个指示延迟何时完成的标志。就像一个循环,它本质上会暂停所有例程中代码的执行(但仍检查 Function3 中的 yield 语句),直到标志切换为真。但我猜那是行不通的,因为更新直到“帧”结束(无论是什么)都不会执行。我不敢相信一个简单的延迟就这么难编码。
  • yield Function2() 比使用回调更有意义。
【解决方案2】:

您应该让 Function1 和 Function2 都返回 IEnumerator,然后让步给它们调用的函数:

IEnumerator public Function1()
{
    ...
    yield return Function2();
    ...
}
IEnumerator public Function2()
{
    ...
    yield return Function3();
    ...
}
IEnumerator public Function3()
{
    ...
    yield return new WaitForSeconds(.5f); // Or whatever
    ...
}

现在调用StartCoroutine(Function1()) 而不是Function1(),在调用它时。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-05
    • 2020-11-22
    • 2011-01-29
    • 2016-05-03
    • 1970-01-01
    • 2011-03-01
    相关资源
    最近更新 更多