- Home /
How do Coroutines behave with Triggers?
Hi,
Lets say I have this code:
void OnTriggerEnter2D (Collider2D other)
{
if (other.gameObject.tag == "Player")
{
StartCoroutine (DoSomething());
}
}
IEnumerator DoSomething()
{
while (true)
{
DoMoreStuff();
}
yield return null;
}
The questions is will each trigger create a new Coroutine that runs infinitely?
What if the condition is false? Is the coroutine still in memory but not doing anything?
Thanks in advance.
this indeed crashes unity.
anyway the main point is that since coroutines stay alive frame after frame, more coroutines are created and you waste resources.
this is clear now.
thanks.
Answer by DanSuperGP · Jan 07, 2015 at 01:27 AM
The code you posted will crash Unity the first time it executes.
while(true)
{
DoMoreStuff()
}
is an infinite loop.
If you were to put the yield return null inside the loop instead of outside, Unity will not crash... but it will "DoMoreStuff()" every frame forever.
The answer to your first question is, yes, each call to StartCoroutine() will start a new coroutine, that will run infinitely (assuming you fix the infinite loop)
The answer to your second question is, no. If the condition is not met, then StartCoroutine will just not be called.
If you want to avoid this happening, you can do this.
private bool hasCoroutineStarted = false;
void OnTriggerEnter2D (Collider2D other)
{
if (other.gameObject.tag == "Player" && ! hasCoroutineStarted)
{
hasCoroutineStarted = true;
StartCoroutine (DoSomething());
}
}
IEnumerator DoSomething()
{
while (true)
{
DoMoreStuff();
yield return null;
}
}
This will start your infinite coroutine once, and it will not crash Unity.
You said "This will start your infinite coroutine once, and it will not crash Unity"
I am wondering, why will it not crash unity when "while (true)" is an infinite loop ? Am I missing something?
Answer by StrikeMasterz · Jan 07, 2015 at 12:52 AM
Here is all your code. I have added comments so you can see what exactly is happening:
//OnTriggerEnter2D, which runs the command in the block if the object hits another 2D
//object
void OnTriggerEnter2D (Collider2D other)
{
//If the object that this gameObject hits has the tag player
if (other.gameObject.tag == "Player")
{
//Run the Coroutine DoSomething()
StartCoroutine (DoSomething());
}
}
//Coroutine DoSomething
IEnumerator DoSomething()
{
//As long as true is true (this effectively means this code will run infinitely)
while (true)
{
//Do Other Commands
DoMoreStuff();
}
//Normally this would stop the couroutine, but the Engine never gets here
//since its still doing DoMoreStuff() forever;
yield return null;
}
What this code essentially does is activate a Couroutine when the gameObject hits an object with the tag Player. This couroutine will then rune the while(true), which since has the arguement true will run forever until something sets it to false. This would also have the negative side-effect of crashing, since it would repeat infinately, never go to the next section and will crash the engine eventually.
It never reaches the yield return null, which should stop the couroutine, since its still busy doing the while(true) forever. If you were to set it to while(false), then it would skip that whole while section and end the Couroutine for that frame. It will then come back in the next frame, but since there is nothing else do to (since while(false)), then it will simply end it and repeat later on.
There is no real reason to make a Couroutine with the above script, it would have been better to up into an Update/FixedUpdate/LateUpdate or inside the OnTriggerEnter2D. The reason you use a Couroutine is to make a script that keeps repeating itself, but you can choose how long it waits before it repeats, such as after 2 frams or 4 seconds.
It would be much more useful if you put the yield return null inside the while loop to stop the whole couroutine until some time:
IEnumerator DoSomething()
{
while (true)
{
DoMoreStuff();
yield return new WaitForSeconds(5f);
}
}
When you launch this code, it will activate the while(true) untill it reaches the yield section. It will then stop the Coroutine (effectivly stopping the while() method aswell) and wait 5 seconds. It will then repeat where it left of, which is in the end of the while loop. Then it will simply go back to the start of the while loop, keep doing DoMoreStuff(); then stop and wait for 5 seconds to do the same thing all over again.
thanks, makes sense.
so i guess this is not a clean thing to do since it would add a lot of coroutines that dont do anything but check constantly for the while loop to be true.
does anyone one know how bad this is?
thanks
Yes. There is no real reason to make a Couroutine with the above script, it would have been better to up into an Update/FixedUpdate/LateUpdate or inside the OnTriggerEnter2D. The reason you use a Couroutine is to make a script that keeps repeating itself, but you can choose how long it waits before it repeats, such as after 2 frams or 4 seconds.
yield return null
doesn't stop a coroutine. It pauses till the next frame.
yield break
stops coroutines.
Also as I noted in my answer, the while loop in this answer will immediately crash Unity.
It would be much more useful if you put the yield return null
inside the while loop to stop the whole couroutine until some time:
IEnumerator DoSomething()
{
while (true)
{
Do$$anonymous$$oreStuff();
yield return new WaitForSeconds(5f);
}
}
When you launch this code, it will activate the while(true) untill it reaches the yield section. It will then stop the Coroutine (effectivly stopping the while() method aswell) and wait 5 seconds. It will then repeat where it left of, which is in the end of the while loop. Then it will simply go back to the start of the while loop, keep doing Do$$anonymous$$oreStuff(); then stop and wait for 5 seconds to do the same thing all over again.
Your answer
Follow this Question
Related Questions
Coroutines IEnumerator not working as expected 2 Answers
Damager Powerup issue - NullReferenceException: Object reference not set to an instance of an object 2 Answers
Use Coroutine when object rotates 2 Answers
Updating a Value in OnTriggerEnter and Returning That Value Immediately... 0 Answers
coroutine in update method 1 Answer