one static networking function

I have been making my game and it has been coming along very nicely but I have found that I am continually making IEnumerator functions in nearly every script to communicate with the server.

Is there a simpler way to make say 1 static IEnumerator to send data to the server and then return the data to the script that called it?

The only way I can really think of is to make a static IEnumerator function and at the top of that script make variables to get all the script components in my app and then when the data returns call script.function() to send the data back to the script…Anyone come up with anything easier?

You might want to give an example of what you’re doing. In my own networking system I rarely use IEnumerators, so there’s probably an alternative approach to what you’re trying to do. What are your IEnumerators doing?

For example, I use a system where each network aware GameObject has a component I call JCGIdentity. It has a unique ID number and maintains a list of all network aware scripts on the GameObject. So a message from a specific script gets tagged with the ID number of the object and the index number of the script, and a return message just needs to use the same to go back to the same script.

Network aware scripts with methods which receive network messages maintain a list of delegates of those receiver methods. I call them RPC’s just because most network systems do so. I just include the index number of the specific RPC to get the correct one called on the script. So all in all when I send an RPC I include the ID number of the GameObject, the index of the script, and the index of the RPC delegate I want called to handle the data.

In my last project that needed to communicate with a server, I used a singleton MonoBehavior for managing the actual network communication, and it had coroutine with parameters for what URL to contact, what data to send to it, and a generic parameter for what kind of data type to parse the returned data into.

In almost every single of my networked applications I rarely used enumerators to do any data transfer with the server or client. Try checking out event driven examples and async networking methods.
Also it would help a lot if you can provide even a little example from your code :slight_smile:

I’ve always been fond of setups where you pass in a callback lambda to the network call, which gets invoked automatically when the response comes back. In Unity (or any user-interactive framework) you have to be cognizant of which thread your callback gets run on though, assuming the callback touches any Unity objects. Unity typically requires most of its objects to only be accessed on the main thread.

1 Like

Ah yes, I forgot to mention that Unity API is really not thread safe. If going with an async multi threaded approach that must be considered before hand. It is doable with work arounds and custom interfaces but still a pain never the less ^^

Sure let me provide an example sorry was pretty busy yesterday.

public void startfriends()
    {
             StartCoroutine(contactserver(21));
    }

IEnumerator contactserver(int e)
{
    WWWForm form = new WWWForm();
    form.AddField("actiontyp", e);
    UnityWebRequest www = UnityWebRequest.Post("url/dostuff.php", form);
    yield return www.SendWebRequest();
    if (www.isNetworkError || www.isHttpError) { Debug.Log("Error contacting Server"); }
    else
    {
        string returndata = www.downloadHandler.text;
        Debug.Log(returndata);
        if (returndata.Length > 2)
        {
            string[] myarray = returndata.Split('|');
            if (myarray[0] == "1")
            {
                int c = 0;
                foreach (string row in myarray)
                {
                    if (row.Length > 2)
                    {
                        string[] rowdata = row.Split('

So what I have been doing is linking a button onclick to a function that then starts a coroutine and calls the ienumerator function to contact the php server. Depending on the actiontype the php server does what it needs to do in this case get your friends from a mysql database and then return a string to the server like
0|error if there is an error or 1|data if it was successful.

If after it splits the returned string myarray[0] = 1 then I send the data to a function to generate the friends page otherwise it will call the domessage function which pops up a window with the error message.

Currently i have been doing this on every script that needs to contact the php server which is a lot of scripts so was wanting to hopefully do when a button is clicked it sends a call to contactserver and then when the server returns it will split the string and see if str[0] is a 0 (error) or 1 (worked) and if error do the error message or if 1 then send the data to a function in that script.

My current way works but just looks a bit messy in all the scripts.);
//add each friend to dictionary
// render friend prefabs
}
}
}
else { errorscr.domessage(myarray[1]); }
}
else { errorscr.domessage(“ERROR RECEIVING DATA FROM SERVER”); }
}
}


So what I have been doing is linking a button onclick to a function that then starts a coroutine and calls the ienumerator function to contact the php server. Depending on the actiontype the php server does what it needs to do in this case get your friends from a mysql database and then return a string to the server like
0|error if there is an error or 1|data if it was successful.

If after it splits the returned string myarray[0] = 1 then I send the data to a function to generate the friends page otherwise it will call the domessage function which pops up a window with the error message.

Currently i have been doing this on every script that needs to contact the php server which is a lot of scripts so was wanting to hopefully do when a button is clicked it sends a call to contactserver and then when the server returns it will split the string and see if str[0] is a 0 (error) or 1 (worked) and if error do the error message or if 1 then send the data to a function in that script.

My current way works but just looks a bit messy in all the scripts.

Lambdas! Delegates! Try this in a central place:

public IEnumerator contactserver(UnityWebRequest www, Action<string> callbackHandler)
{
    yield return www.SendWebRequest();
    if (www.isNetworkError || www.isHttpError) { Debug.Log("Error contacting Server"); }
    else
    {
        string returndata = www.downloadHandler.text;
        callbackHandler(returnData);
    }
}

Then your code can either use predefined functions:

UnityWebRequest req = BuildRequest();
StartCoroutine(ContactServer(req, OnResponseReturned));

// In the same class, the callback function:
void OnResponseReturned(string response) {
  Debug.Log("I can do whatever I want with this response: " + response);
}

Or it can use lambdas to define the callback inline.

UnityWebRequest req = BuildRequest();
StartCoroutine(ContactServer(req, (response) => {
  Debug.Log("Response was " + response");
  // Do whatever else you want to do.
}));

I am not too sure about the lambda stuff right now i have this

    private Bank bankscript;
    private Battle battlescript;
    private friend friendscript;
   // need about 20 more of these

    void Start()
    {
        bankscript = GameObject.Find("bankcanvas").GetComponent<Bank>();
        battlescript = GameObject.Find("battlecanvas").GetComponent<Battle>();
        friendscript = GameObject.Find("friendcanvas").GetComponent<friend>();
        //needs to get 20 more of these
    }

    public static IEnumerator DoServer(int i, WWWForm form)
    {
        UnityWebRequest www = UnityWebRequest.Post(url, form);
        yield return www.SendWebRequest();
        if (www.isNetworkError || www.isHttpError)
        {
            error.domessage("Error contacting Server");
        }
        else
        {
            string returndata = www.downloadHandler.text;
            Debug.Log(returndata);
            if(returndata.Length < 2) { error.domessage("error occured"); yield break; }
            string[] myarray = returndata.Split('|');
            if (myarray[0] == "1")
            {
        switch (i)
                {
                    case 1: bankscript.updatebanking(returndata);
                    case 2: battlescript.updatebattle(returndata);
                    case 3: friendscript.renderfriends(returndata);
                   //needs 20 more cases
                }
            }
            else
            {
                error.domessage("error occured");
            }
        }

    }

What i am basically wanting is in say the bank script there will be a function

    public void dobanking(int a)
    {
        var inputamt = Regex.Replace(depamt.text, "[^0-9]", "");
        WWWForm form = new WWWForm();
        form.AddField("banktyp", "1");
        form.AddField("amount", inputamt);
        form.AddField("actiontyp", a);
        StartCoroutine(Serverscript.DoServer(1,form));

    }

so the bankscript will then start the coroutine in the Serverscript script and run but what i want after it runs is to send the data it got from the server back to a function in the bankscript. I have about 20 different scripts that will need to call this coroutine in the Serverscript script and then once the data is returned, return the fetched data to a function in the script that called it.

Is this something you can do with lambdas or is the way i have started to do it above the only way?

Look at my post. My middle example is exactly that.

1 Like

Cheers that works extremely well will allow me to clear up a lot of useless code now, extremely grateful for your help :slight_smile:

One thing i did notice and im guessing you just mixed up variables but just wanted to make sure
when you say
IEnumerator contactserver(UnityWebRequest www, Action callbackHandler)

but then later you just call handler(returnstring); I changed handler to callbackHandler and it worked, is this correct?

Yep, sorry that was a typo!