I was under the presumption that you could yield return an IEnumerator and the execution would go through that IEnumerator and then continue down the code.
It works in some scenarios, not all. I’m usually running the whole thing with StartCoroutine()
Can you not chain them like that?
That should work. I’ve done that many times and never had an issue. Are they not running at all or are they just starting and then immediately going to the next line?
I assume you’re calling StartCoroutine to start a main IEnumerator, then within that you’re calling the others with yield return? What are the differences between the IEnumerators that work like you expected vs the ones that don’t? They need to have some kind of wait condition in order for the execution of the main coroutine to pause, otherwise it’ll run it and immediately move to the next line like a regular method would (technically after waiting a frame if you call ‘yield return null’).
Alright that’s fantastic news. Yes I’ve got an IEnumerator that yield returns other IEnumerators and then run the whole thing with StartCoroutine.
It did not execute at all, but I’ve moved it to another IEnumerator and it works now. I just needed to be sure I wasn’t misunderstanding how IEnumerators work. Thanks a lot
No problem, glad it’s working!
Ah you know what. I think I know what’s wrong. I made an IEnumerator function that takes in a list of IEnumerators and iterates on them in sync, with a simple code:
bool doMoveNext;
do
{
doMoveNext = false;
for (int i = 0; i < enumeratorList.Length; i++)
doMoveNext |= enumeratorList[i].MoveNext();
yield return null;
}
while (doMoveNext);
And my guess is that the .MoveNext() simply jumps over the yield return IEnumerator which is why it never ran. Maybe Unity’s Coroutine checks every .Current if it returns another IEnumerator and then iterates on that
If you want to start a blocking coroutine in another coroutine, you need to return the value of StartCoroutine
IEnumerator MyCoroutine()
{
yield return StartCoroutine(AnotherCoroutine());
// code from here will execute once AnotherCoroutine finishes
}
This code is going to make it so every coroutine in your list has all of its yield instructions ignored and essentially replaced with a yield return null
. Unity’s coroutine processor looks at the Current value of every enumerator and does different behavior based on different types of yield instructions. Your code ignores those values and just forces its own paradigm of yielding for one frame each time.
So what I said here
was correct
I do not want to start a blocking coroutine. That is why I made the specific function. To run them in sync.
Yes. Unity is checking the Current value for any YieldInstruction (https://docs.unity3d.com/ScriptReference/YieldInstruction.html) which includes all the WaitForXXX instructions, CustomYieldInstructions, and other Coroutines.
You should just be able to call StartCoroutine in the other coroutine without yielding the result.
IEnumerator MyCoroutine()
{
StartCoroutine(AnotherCoroutine());
// code from here will execute regardless of what AnotherCoroutine does
yield return null;
}
I might be wrong, but if you want to execute a list of IEnumerators waiting for each one to complete before moving to the next, couldn’t you just do this:
IEnumerator MainCoroutine()
{
for (int i = 0; i < enumeratorList.Length; i++)
{
yield return enumeratorList[i];
}
}
No coroutines complete each IEnumerator before continuing. This would simply chain them up.
Yes but I need to control them both at the same time. Which is why they need to be joined up.
I don’t think I am understanding what you are trying to accomplish. Perhaps you could give an example? I don’t really understand what running a coroutine in “sync” means.
I’m confused too because I’m pretty sure the behavior OP is trying to reproduce is just the default behavior of Unity.
I found a git repository that does everything I was looking for. It has the feature of Combine which takes in multiple IEnumerators and returns another IEnumerator that runs them at the same time, exactly what I was trying to do above.