- Home /
Fire and forget coroutines
I have a number of performance-heavy methods that don't need to finish at the same time as the main method. I've been trying to use them as coroutines such as the following:
IEnumerator Example() {
yield return null;
Do stuff ...
}
Then I simply call them with StartCoroutine(), and it works great in the editor, reducing spikes and so-on. However, on the device it appears to never resume the coroutine. Do I really need to yield return StartCoroutine(Example()); ? Or is it possible to fire-and-forget them and trust that they will execute to the end?
Answer by sandworm · Aug 02, 2012 at 02:37 AM
Ok, solved my own problem. Turns out the object that calls the StartCoroutine cannot be destroyed in the next frame, or the called coroutine will never get past the first yield statement. I guess the coroutine is tied to the caller. Once I switched the caller to a persistent GO, it worked perfectly.
Yes the coroutine executor is the object that called the StartCoroutine().
Note that if you call a coroutine on another object, neither the caller or this other object should be destroyed, meaning you can't fire and forget this way.
A workaround is to have the caller call a simple method that will in turn start the coroutine. Something like (not tested):
public class Caller : $$anonymous$$onoBehaviour
{
public ScriptWithCoroutine swc;
void Some$$anonymous$$ethod()
{
swc.SomeAction();
}
}
public class ScriptWithCoroutine : $$anonymous$$onoBehaviour
{
public void SomeAction()
{
StartCoroutine(DoSomeAction());
}
IEnumerator DoSomeAction()
{
bool finished = false;
while (!finished)
{
// do some expensive and iterative work
yield return null;
}
}
}
This is awesome info, thanks. It's something I never realized about coroutines, why isn't it in the docs?
@$$anonymous$$ryptos: That's not entirely true ;) In your case the caller can be destroyed without any problems since your coroutine runs on the ScriptWithCoroutine instance since you called StartCoroutine on this instance.
StartCoroutine(DoSomeAction());
// is the same as
this.StartCoroutine(DoSomeAction());
So the coroutine runs on the swc $$anonymous$$onoBehaviour. The Caller class isn't involved except it is calling StartCoroutine.
But, maybe that's what you've ment, when you use StartCoroutine of another $$anonymous$$onoBehaviour, the object that contains the coroutine should not be destroyed and the object the coroutine runs on should not be destroyed:
public class Caller : $$anonymous$$onoBehaviour
{
public ScriptWithCoroutine swc;
void Start()
{
StartCoroutine(swc.SomeAction());
}
}
public class ScriptWithCoroutine : $$anonymous$$onoBehaviour
{
public IEnumerator DoSomeAction()
{
bool finished = false;
while (!finished)
{
// do some expensive and iterative work
yield return null;
}
}
}
In this case the coroutine belongs to the swc object, but it runs on the Caller instance.
@Bunny83 that is exaclty what I meant. The piece of code I gave was a solution to prevent this issue (hence the word workaround in my comment). ;)
Yes, sorry, i get that wrong ;)
Another workaround is to call StartCoroutine of the desired owner:
public class Caller : $$anonymous$$onoBehaviour
{
public ScriptWithCoroutine swc;
void Start()
{
swc.StartCoroutine(swc.SomeAction());
}
}
public class ScriptWithCoroutine : $$anonymous$$onoBehaviour
{
public IEnumerator DoSomeAction()
{
bool finished = false;
while (!finished)
{
// do some expensive and iterative work
yield return null;
}
}
}
Your answer
Follow this Question
Related Questions
How To Create Coroutine Delegates? 1 Answer
WaitForSeconds problem with Unity Pro 3 Answers
Yield position within while loop in coroutine 1 Answer
JS Wait for a function to complete - no WaitForSeconds 1 Answer
Coroutines and states 1 Answer