【问题标题】:Unity - need to return value only after coroutine finishesUnity - 仅在协程完成后才需要返回值
【发布时间】:2018-12-02 18:25:54
【问题描述】:

我正在统一开发一款游戏,但遇到了一个我无法解决的问题。 我通过标准 WWW 对象连接到 Web 服务器并使用协程执行 POST 请求。

代码本身可以工作,但我需要更新变量值并在协程完成后返回该变量,我无法做到。

public int POST(string username, string passw)
{
    WWWForm form = new WWWForm();
    form.AddField("usr", username);
    form.AddField("pass", passw);

    WWW www = new WWW(url, form);

    StartCoroutine(WaitForRequest(www));

    //problem is here !
    return success_fail;
}

private IEnumerator WaitForRequest(WWW www)
{

    yield return www;
    if (www.error == null)
    {

            if(www.text.Contains("user exists"))
            {

                success_fail = 2;
            }
            else
            {
                success_fail=1;
            }
    } else {
        success_fail=0;
    }    
}

协程用相关值更新 'success_fail' 的值。 但是'return success_fail;' POST 方法中的行在协程完成之前运行,这会导致它返回一个 false 值。

我尝试使用额外的协程但没有成功,假设我在那里也有错误。 如何仅在协程完成后返回“success_fail”值?

谢谢。

【问题讨论】:

  • 如果你调用另一个协程,它会等到那个协程完成。 answers.unity3d.com/questions/276055/…
  • 您混淆了同步和异步代码。也许回调函数会有用?您可以使用Action<T> 委托,其中T 是您想要“返回”的任何类型。

标签: c# unity3d coroutine


【解决方案1】:

只有一个协程可以等待另一个协程。由于你需要等待你启动的协程(WaitForRequest),这意味着你必须将 POST 转换为协程,它不能返回 int。

看起来success_fail是一个成员变量,所以如果它暴露给启动POST的人(作为协程),你无论如何都不需要返回它。

public int success_fail

IEnumerator POST(string username, string passw)
{
    WWWForm form = new WWWForm();
    form.AddField("usr", username);
    form.AddField("pass", passw);

    WWW www = new WWW(url, form);

    yield return StartCoroutine(WaitForRequest(www));
}

private IEnumerator WaitForRequest(WWW www)
{
    yield return www;
    if (www.error == null)
    {
        if(www.text.Contains("user exists"))
            {
                success_fail = 2;
            }
            else
            {
                success_fail=1;
            }
    } else {
        success_fail=0;
    }    
}

基本上,如果您希望代码“等待”,它必须是协程。您无法在不阻塞整个引擎的情况下进行等待调用(没有某种类型的循环破解)。

这个线程提供了一种方法,如果你真的需要,你可以从协程中返回 int,但 POST 仍然不能是阻塞调用......

http://answers.unity3d.com/questions/24640/how-do-i-return-a-value-from-a-coroutine.html

【讨论】:

  • 我试过这个,但是调用 POST 作为协程的方法不会等待在下一行继续执行。所以不能解决success_fail要更新的值。
  • @Caco POST 应该使用 StartCoroutine(POST(usename, passw)); 调用
  • 是的,我使用StartCoroutine 调用,但调用后程序流程并没有停止。在IEnumerator POST 方法中,第二个yield return 确实会停止执行,但第一个不会。
  • 听起来是对的。协程的整个想法是它不会停止执行。您必须调用 yield 来等待它完成,就像行 yield return StartCoroutine(WaitForRequest(www)) 一样。你只是在调用堆栈中做的更高。
【解决方案2】:

函数在返回之前不会等待协程,但是您可以使用 Action 来提供某种返回。

把它放在你的 Start 函数中

WWW www = new WWW("http://google.com");

StartCoroutine(WaitForRequest(www,(status)=>{
    print(status.ToString());
}));

并添加这个。

private IEnumerator WaitForRequest(WWW www,Action<int> callback) {
    int tempInt = 0;
    yield return www;
    if (string.IsNullOrEmpty(www.error)) {
        if(!string.IsNullOrEmpty(www.text)) {
            tempInt = 3;
        }
        else {
            tempInt=2;
        }
    } else {
        print(www.error);
        tempInt=1;
    }
    callback(tempInt);
}

试一试,虽然该函数可以更改一个值,但它不会返回值并且只有一个参数。因此,从本质上讲,这不是返回协程的解决方案,但是一旦从协程接收到 int,我们就可以证明如何处理它,甚至可以从回调中调用其他函数。

StartCoroutine(WaitForRequest(www,(status)=>{
    print(status.ToString());
    Awake(); // we can call other functions within the callback to use other codeblocks and logic.
    if(status != 0)
        print("yay!");
    }
));

这可能对你有用。 http://answers.unity3d.com/questions/744888/returning-an-ienumerator-as-an-int.html

【讨论】:

    【解决方案3】:

    https://stackoverflow.com/a/67805727/13098229网络请求请参考这里

    不要使用WWW,而是使用UnityWebRequest

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-07-03
      • 2018-09-29
      • 2022-01-24
      • 2016-12-10
      相关资源
      最近更新 更多