【问题标题】:How to wait Coroutine callback is executed?如何等待协程回调被执行?
【发布时间】:2018-09-19 11:23:27
【问题描述】:

我想等待 StartCoroutine 回调被执行。 有人知道怎么做吗?

public float getXXX() {
  var result;
  StartCoroutine(YYY((r) => result = r)); // how to wait this?
  return result;
}

private IEnumerator YYY(System.Action<float> callback) {
  LinkedList<float> list = new LinkedList<float>();
  while(timeleft > 0) {
    timeleft -= Time.deltaTime;
    list.add(transform.position.magnitude);
    yield return new WaitForSeconds (WAITSPAN);
  }

  callback(list.max());
  yeild return true;
}

【问题讨论】:

标签: c# unity3d


【解决方案1】:

您不能也不应该尝试等待或让一个协程函数从协程函数(getXXX 函数)返回。它将阻塞该非协程函数,直到该函数返回阻止其他 Unity 脚本运行。

要在 getXXX 函数中等待协程函数 (YYY),您还必须在协程函数中创建您正在调用和等待的函数。在这种情况下,这是YYY 函数,所以它也应该是一个协程函数,然后你可以yield 它:

public IEnumerator getXXX()
{
    float result = 0f;
    yield return StartCoroutine(YYY((r) => result = r)); // how to wait this?

    //Use the result variable
    Debug.Log(result);
}

如果你不想让getXXX 函数成为协程函数,那么不要试图在那里等待。您仍然可以使用来自YYY 协程函数的结果,但不要尝试返回结果。只需使用它在该功能中执行您想做的任何事情:

public void doSomethingXXX()
{
    StartCoroutine(YYY((result) =>
    {
        //Do something with the result variable
        Debug.Log(result);

    }));
}

使用协程的想法是能够在多个帧上做某事。 void 函数只会在一帧内完成。您不能在 void 或非 IEnumerator/协程函数中产生/等待。

【讨论】:

  • 感谢您的回复。我必须在 getXXX() 上返回一些值。而且我必须在 YYY 中使用“yield return new WaitForSeconds()”。如果我使用它,调用方方法会在整个 YYY 进程完成之前恢复进程......你知道我该如何避免这种情况吗?
  • “如果我使用这个,调用者方法会恢复进程。”我不明白。你能说得更具体一点吗?
  • 在YYY中,每隔一段时间调用WaitForSeconds.like ..while(time>0){ //一些代码..return (WaitForSeconds (1.0f)} 调用WaitForSeconds时,会处理XXX无需等待 YYY 处理完成即可恢复。
  • 您是在谈论问题中的public float getXXX() 函数吗?就像我在回答中所说的那样,您不能让它等待协程或使用 WaitForSeconds 等待,因为 getXXX 不是协程函数。
【解决方案2】:

您只能在协程内等待。为此,您的 getXXX() 方法也应该是协程。像这样的:

public float someOtherMethod()
{
    float result;
    StartCoroutine(getXXX(out result));
    return result;
}

IEnumerator getXXX(out float result)
{
    //more code here...
    yield return StartCoroutine(YYY((r) => result = r));
    //more code here...
}

IEnumerator YYY(System.Action<float> callback)
{
    //your logic here...
}

【讨论】:

    【解决方案3】:

    我发现您可以调用该类并使用此代码中的方法并修改以使用它与您的代码非常相似但不太复杂:

    using UnityEngine;
    using System.Collections;
    
    public class WaitForSecondsExample : MonoBehaviour
    {
       void Start()
       {
            StartCoroutine(Example());
       }
    
        IEnumerator Example()
        {
            print(Time.time);
            yield return new WaitForSeconds(5);
            print(Time.time);
        }
     }
    

    此代码取自:https://docs.unity3d.com/ScriptReference/WaitForSeconds.html 从那里的例子 5 是它将等待的时间,除非您想基于某些东西动态地执行此操作。取决于你想做什么。但是请注意他们是如何在 StartCoroutine(Example()) 中调用方法 Example() 的,该方法将转到 IEnumerator Example() 并在其中有 WaitForSeconds(5);这将使 StartCoroutine 等待 5 秒。这可以通过在 IEnumerator Example() 中调用该类中的另一个方法来进行硬编码或动态等待,这只是您可以攻击它的众多方法之一。再次取决于你想做什么。实际上,你甚至可能最好将它变成一个方法,每次像

        IEnumerator Example(float flSeconds)
        {
            print(Time.time);
            yield return new WaitForSeconds(flSeconds);
            print(Time.time);
        }
    

    这样你就可以传递你的 LinkedList 列表 = 新的 LinkedList(); 每次

    【讨论】:

    • 这没有回答问题。它只展示了如何等待几秒钟,而不是如何等待协程函数或回调返回。
    猜你喜欢
    • 2022-01-22
    • 2019-12-19
    • 1970-01-01
    • 1970-01-01
    • 2020-07-03
    • 2021-06-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多