IEnumerator Refresh(float waitSeconds)
{
MasterServer.ClearHostList();
MasterServer.RequestHostList(hostName);
Debug.Log(“Refresh metod”);
yield return new WaitForSeconds(3);
}
HostData[] ReturnHostList()
{
StartCoroutine(Refresh(3.0f));
hostData = MasterServer.PollHostList();
Debug.Log("Return Metod");
return hostData;
}
void PressHostList()
{
Debug.Log("Pressed");
gameObject.animation.Play();
hostData = networkOperationLibraryScript.ReturnHostList();
if(hostData.Length!=0)
InstantiateHostList();
}
I attached a function named PressHostList to an EZGui button.This PressHostList function calls ReturnHostList function from another GameObjects script.That function named ReturnHostList supposed to return a HostData array.But first it has to refresh it so it calls a function named Refresh which is responsible for refreshing HostData array.Refresh function has to wait between requesting hostlist and polling that host list.Okay.My problem is,ReturnHostList function does not wait for Refresh function to be completed.It calls refresh function but suddenly returns
When you use StartCoroutine, it sets the coroutine running, but unless it is called from within another coroutine using yield return, the function it was called from goes on with whatever it was doing. Putting your yield return new WaitForSeconds at the end of the coroutine like that will do nothing, because by the time it gets to that line it’s already done everything that it was going to do!
The biggest problem, from a design point of view, is that you do not want to wait for 3 seconds before returning that array anyway, because this will cause a 3-second lag for the user! Instead of directly requesting a refresh, you should just poll MasterServer.PollHostList() once every frame or so (maybe have something in the Update loop which assigns to a local variable) and then return that stored variable whenever your button gets pushed. Then have a separate button for manually resending the request for host data, which calls MasterServer.RequestHostList(). Basically, there’s no need to wait 3 seconds in any of this- just use PollHostList(), and the array of HostData objects will arrive when it arrives- just recheck it every frame. The actual time your user will have to wait will depend on the connection to the Master Server.
Place a debug instruction like print(“Pause Ended”); right after WaitForSeconds and you will see the message after 3 seconds, as expected. StartCoroutine does exactly what its name says: it starts the coroutine and return immediately. You must change your logic to get the result you want - maybe moving most of the code to the coroutine. You must also use a bool flag to avoid starting the coroutine again while it’s running. That’s something following this idea (I’m a JS guy, thus check this for C# errors):
bool gettingList = false;
HostData[] hostData;
IEnumerator GetList(float waitSeconds){
if (!gettingList){ // do nothing if GetList already running
gettingList = true; // signal "I'm working"
gameObject.animation.Play();
MasterServer.ClearHostList();
MasterServer.RequestHostList(hostName);
Debug.Log("Refresh metod");
yield return new WaitForSeconds(3);
hostData = MasterServer.PollHostList();
Debug.Log("Got list");
if(hostData.Length!=0)
InstantiateHostList();
gettingList = false;
}
}
void PressHostList(){
StartCoroutine(GetList(3.0f));
}
Following can be reasons due to which your coroutine gets stuck on WaitForSeconds
:
-
The time given in WaitForSeconds
is too long. Although this is silly reason, but sometimes this happens
-
The object from which you are calling the coroutine is getting destroyed. You can check that as follow.
void OnDestroy() {
Debug.Log("Destroyed");
}
-
From any place, StopAllCoroutines()
is getting called which is stopping your coroutine.
-
Lastly, check that anywhere Time.timeScale
is getting set to 0. Because when its zero, it stops Time.deltaTime
from increasing and as a result WaitForSeconds
never reaches your specified value.You can check your current timescale in Edit -> Project settings -> Time
check Time Scale parameter in that. Or you check its value by logging before your coroutine is called.