Search Unity

C# Coroutine for WWW

Discussion in 'Scripting' started by AmazingRuss, Mar 22, 2009.

  1. AmazingRuss

    AmazingRuss

    Joined:
    May 25, 2008
    Posts:
    933
    Is there an example somewhere of how to write a coroutine in C# to wait on a WWW response? I've been using Invoke to do it, because I just can't get the coroutine to work. What would the coroutine equivalent of this be?:

    Code (csharp):
    1.  
    2.         void GetResponse()
    3.     {
    4.         if(!post.isDone)       
    5.             Invoke("GetResponse", 0.3f);
    6.            
    7.         else if(post.error != null)
    8.             Debug.Log(post.error);
    9.  
    10.         else
    11.             Debug.Log("Submission complete");      
    12.     }

    (post is a WWW object)
     
  2. AngryAnt

    AngryAnt

    Keyboard Operator

    Joined:
    Oct 25, 2005
    Posts:
    3,045
    Something like this?
    Code (csharp):
    1. // Whenever you need to do a WWW request
    2. StartCoroutine( HandleWWW( myWWW ) );
    3.  
    4. public IEnumerator HandleWWW( WWW theWWW )
    5. {
    6.     // pre-www actions //
    7.     yield theWWW;
    8.     // post-www actions //
    9. }
     
  3. AmazingRuss

    AmazingRuss

    Joined:
    May 25, 2008
    Posts:
    933
    Is that C#? The function won't compile for me.
     
  4. AngryAnt

    AngryAnt

    Keyboard Operator

    Joined:
    Oct 25, 2005
    Posts:
    3,045
    Ah sorry. Untested code and its been a while since I toyed with the WWW class. Regardless, the yield statement should be "yield return theWWW" - still untested though ;)
     
  5. AmazingRuss

    AmazingRuss

    Joined:
    May 25, 2008
    Posts:
    933
    That's better...thanks!

    I have some weird learning defect about coroutines...it's very annoying.
     
  6. thecreatrix

    thecreatrix

    Joined:
    Dec 19, 2008
    Posts:
    94
    Wild and crazy thought here, but would using a delegate work better (or at least equivalently)?
     
  7. AngryAnt

    AngryAnt

    Keyboard Operator

    Joined:
    Oct 25, 2005
    Posts:
    3,045
    I don't see where WWW allows you to feed it a delegate? Perhaps I'm misunderstanding your idea?
     
  8. thecreatrix

    thecreatrix

    Joined:
    Dec 19, 2008
    Posts:
    94
    I meant as an alternative approach, maybe you could use a delegates instead of a coroutine, ie, fire an event when the WWW request completes. It might be a simpler way that would yield (ha!) the same effect.

    The OP seemed to be struggling with coroutines, and perhaps it's not the only way to go about it. Then again, I'm a Unity Noob and maybe coroutines are the "Unity Way" for this type of thing. :)
     
  9. AmazingRuss

    AmazingRuss

    Joined:
    May 25, 2008
    Posts:
    933
    I ended up using both:

    Code (csharp):
    1.  
    2. using UnityEngine;
    3. using System.Collections;
    4.  
    5. public class ScoreTable : MonoBehaviour
    6. {
    7.     enum State {Idle, GettingText, SubmittingScore};
    8.     State state;
    9.    
    10.     public delegate void CallBack(bool result);
    11.     CallBack callBack;
    12.    
    13.     public string error;
    14.    
    15.     //------------------------------------------------------------
    16.     public void Post(string pName, int score, string url)
    17.     { Post(pName, score, url, null); }
    18.  
    19.     //------------------------------------------------------------
    20.     public void Post(string pName, int score, string url, CallBack cb)
    21.     {
    22.         callBack = cb;
    23.       string hash = QMd5.Sum(pName + score + iPhoneSettings.uniqueIdentifier + "float i");
    24.    
    25.         url += "?name=" + WWW.EscapeURL(pName)
    26.             + "&score=" + score
    27.             + "&UDID=" + iPhoneSettings.uniqueIdentifier
    28.             + "&hash=" + hash;
    29.  
    30.         StartCoroutine( HandleWWW( new WWW(url) ) );
    31.     }
    32.  
    33.     //------------------------------------------------------------
    34.     IEnumerator HandleWWW( WWW r )
    35.     {
    36.         state = State.SubmittingScore;  
    37.  
    38.         yield return r;
    39.  
    40.         state = State.Idle;
    41.            
    42.         if(callBack != null)
    43.         {
    44.             callBack( r.error == null );
    45.             callBack = null;
    46.         }
    47.        
    48.         error = r.error;
    49.     }
    50.            
    51. }
    52.  
    53.  
     
  10. AngryAnt

    AngryAnt

    Keyboard Operator

    Joined:
    Oct 25, 2005
    Posts:
    3,045
    Very nice - one point: Why rely on a global variable to hold your callback reference rather than just passing along as a parameter to your coroutine?
     
  11. AmazingRuss

    AmazingRuss

    Joined:
    May 25, 2008
    Posts:
    933
    Sounds good....the way it is now is an artifact of the Invoke method I was using before.

    Thanks for the tip!