2015-05-15 13 views
5

Sto lavorando a un gioco in unità e ho riscontrato un problema che non riesco a risolvere. Mi collego a un server Web tramite un oggetto WWW standard e utilizzo di una coroutine per eseguire una richiesta POST.Unity: è necessario restituire il valore solo al termine della coroutine

Il codice in sé funziona, ma ho bisogno di aggiornare un valore variabile e restituire quella variabile una volta terminata la coroutine, che non sono in grado di fare.

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; 
    }  
} 

La coroutine aggiorna il valore di 'success_fail' con il valore pertinente. Ma "return success_fail;" la riga nel metodo POST viene eseguita prima della fine della coroutine, il che fa sì che restituisca un valore falso.

Ho provato a utilizzare una coroutine aggiuntiva ma, senza successo, suppongo di avere anche un errore. Come posso restituire il valore 'success_fail' solo al termine della coroutine?

Grazie.

+0

Se chiami un'altra coroutine, aspetterà fino a che la coroutine è finita. http://answers.unity3d.com/questions/276055/question-about-coroutines-and-waiting-for-a-functi.html – Shelby115

+0

Stai mescolando codice sincrono e asincrono. Forse sarebbe utile una funzione di callback? Si potrebbe usare un 'delegato azione , dove' T' è il tipo che si desidera "restituire". – rutter

risposta

2

Solo una coroutine può attendere un'altra coroutine. Poiché è necessario attendere la coroutine che hai avviato (WaitForRequest), significa che devi convertire POST in una coroutine e non sarà in grado di restituire int.

Sembra che success_fail sia una variabile membro, quindi se questo è esposto a chiunque abbia avviato POST (come una coroutine), non è necessario restituirlo comunque.

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; 
    }  
} 

In sostanza, se si desidera che il proprio codice "aspetti", deve essere una coroutine. Non è possibile effettuare una chiamata che attende senza bloccare l'intero motore (senza alcun tipo di modifica del ciclo).

Questo thread dà un modo in cui si potrebbe restituire l'int dal coroutine se si ha realmente bisogno, ma POST ancora non può essere una chiamata di blocco ...

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

5

funzioni non attendere le coroutine prima del ritorno, tuttavia è possibile utilizzare un'azione per dare una sorta di ritorno.

Dieci in funzione Start

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

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

e aggiungere questo.

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); 
} 

Provatelo, anche se la funzione può modificare un valore, non restituisce un valore e ha un solo parametro. Quindi, in sostanza, questa non è una soluzione per restituire la tua coroutine, ma una volta ricevuto l'int dalla coroutine siamo quindi in grado di giustificare cosa fare con esso e persino chiamare altre funzioni dall'interno del callback.

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!"); 
    } 
)); 

Questo potrebbe essere utile. http://answers.unity3d.com/questions/744888/returning-an-ienumerator-as-an-int.html

+2

Questa dovrebbe essere la risposta accettata. – Programmer