The results of method 1 and method 2 look the same.
It looks like Unity implicitly call StartCoroutine when yield returns IEnumerator.
On which object does a implicitly call to StartCoroutine? game or something else.
I wanted a uniform management of all coroutines. The answer to this question seemed important, but I didn’t find the answer I was looking for in the documentation.
Whatever, thank you for your reply.
public class CustomScript
{
MonoBehaviour m_game;
public Coroutine StartCor(MonoBehaviour game)
{
m_game = game;
return game.StartCoroutine(SomeCoroutine());
}
IEnumerator SomeCoroutine()
{
//1.
yield return CustomMethod();
//2.
yield return m_game.StartCoroutine(CustomMethod());
}
IEnumerator CustomMethod()
{
// do something
yield return new WaitForSeconds(1f);
}
}
If you find the need to “manage” coroutines or run more than one at a time except for trivial “wait” cases, it’s likely an overuse or misuse of coroutines.
It is almost certainly a red flag when you want to implement a system that controls other MonoBehaviour’s coroutines. If they can’t manage their coroutines themselves, all hope of ever being able to debug your code is lost.
This waits for 1 second.
This will throw a NullreferenceException because m_game hasn’t been assigned.
It does not. Unity does not call StartCoroutine on yielded IEnumerators as they are simply iterated in the same coroutine. This behaviour can be seen by explicitly stopping the outer coroutine. When StartCoroutine would be used, the inner coroutine would run independently of the outer one as the outer coroutine just waits for the completion of the inner one. However when you directly yield another IEnumerator, Unity does not start a new coroutine but simply iterates that sub IEnumerator until it is done before resuming the outer one.
This behaviour was changed a long time ago when they introduced the CustomYieldInstruction which does use this new behaviour. In the distant past yielding another IEnumerator did not cause that IEnumerator to be iterated and Unity would just wait one frame.
Over here I posted an example that shows how nested IEnumerators will be stopped with the parent when you stop the parent. The exact implementation of the scheduler we don’t know, since it’s on the native code side. However if I would implement such a feature, I would simply use a Stack of IEnumerators inside the Coroutine object. So the coroutine would simply iterate the top element on the stack which in the usual case is just that one IEnumerator that was passed to StartCoroutine. However when you yield another IEnumerator, the scheduler would simply push that new IEnumerator on the stack. So from now on this coroutine would iterate that nested IEnumerator. Whenever the IEnumerator finishes it is popped from the stack and the previous one is resumed. Once the stack is empty, the coroutine is finished. When you stop that coroutine, it will be removed with all it’s nested IEnumerators as the Coroutine is simply removed from the scheduler.
Wow,so coooool!
This makes it easier to split a very large coroutine without having to introduce a large number of other coroutines.The latter is a disaster if it needs to end halfway.