问题
In my code I have nested IEnumerator methods, such like this :
private IEnumerator PerformRequest(string url) {
// Doing stuff
UnityWebRequest request = UnityWebRequest.Get(url);
yield return request.SendWebRequest();
// Doing stuff
}
private IEnumerator PerformRequest2(string url) {
// Doing stuff
return PerformRequest(url);
// Doing stuff
}
public IEnumerator PerformRequest3(string url) {
// Doing stuff
return PerformRequest2(url);
// Doing stuff
}
I am wondering what is the difference if I add yield
in upper level methods, such like this :
private IEnumerator PerformRequest(string url) {
// Doing stuff
UnityWebRequest request = UnityWebRequest.Get(url);
yield return request.SendWebRequest();
// Doing stuff
}
private IEnumerator PerformRequest2(string url) {
// Doing stuff
yield return PerformRequest(url);
// Doing stuff
}
public IEnumerator PerformRequest3(string url) {
// Doing stuff
yield return PerformRequest2(url);
// Doing stuff
}
Is there a difference, or is it the same behaviour ?
Thank you !
回答1:
Sure, this works
I've done something like this myself before, you can absolutely yield
a method that it itself yeilds, because what happens is that execution is completely linear and when PerformRequest
yields and returns some value (the web request, but not actually important) that propagates up to the yield return...
in PerformRequest2
which then propagates upwards to PerformRequest3
. Unity will resume execuction at the correct location just fine (and you could have answered your own question by testing it, too ;).
Basically its the same as any other nested function, e.g
int GetValue() {
return 4;
}
int GetValue2() {
return GetValue();
}
Is executed exactly the same as (just with a different type):
IEnumerator GetValue() {
return new SomeIEnumerator();
}
IEnumerator GetValue2() {
return GetValue();
}
Which converts to coroutine yielding (yield
is just a special keyword, it doesn't effect return type!):
IEnumerator GetValue() {
yield return new SomeIEnumerator();
}
IEnumerator GetValue2() {
yield return GetValue();
}
You could also do it like this, but I generally don't find any value in it:
IEnumerator GetValue() {
yield return new SomeIEnumerator();
}
IEnumerator GetValue2() {
//other stuff, with yield so our function still returns a value
StarCoroutine(GetValue());
//this stuff runs without waiting
}
Adassko also found this great tutorial about coroutines and nested coroutines.
回答2:
It is worth noting in Draco18s answer, that this:
IEnumerator GetValue() {
// This line won't work.
yield return new SomeIEnumerator();
}
IEnumerator GetValue2() {
//other stuff, with yield so our function still returns a value
StarCoroutine(GetValue());
//this stuff runs without waiting
}
won't work, cause you need to yield the nested coroutine inside a StartCoroutine
call,
so it needs to be:
IEnumerator GetValue() {
// The corrected line.
yield return StartCoroutine(SomeIEnumerator());
}
IEnumerator GetValue2() {
//other stuff, with yield so our function still returns a value
StarCoroutine(GetValue());
//this stuff runs without waiting
}
来源:https://stackoverflow.com/questions/58436172/unity-c-sharp-nested-ienumerator