Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
2
Question by jasonm87 · Jan 07, 2015 at 12:20 AM · coroutineontriggerentercoroutinesienumerator

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.

Comment
Add comment · Show 1
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image jasonm87 · Jan 07, 2015 at 01:46 AM 0
Share

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.

2 Replies

· Add your reply
  • Sort: 
avatar image
3
Best Answer

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.

Comment
Add comment · Show 1 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image mango_khan · Jun 14, 2020 at 03:09 AM 0
Share

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?

avatar image
0

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.

Comment
Add comment · Show 5 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image jasonm87 · Jan 07, 2015 at 01:16 AM 0
Share

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

avatar image StrikeMasterz · Jan 07, 2015 at 01:22 AM 0
Share

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.

avatar image DanSuperGP · Jan 07, 2015 at 01:29 AM 0
Share

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.

avatar image StrikeMasterz · Jan 07, 2015 at 01:30 AM 0
Share

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.

avatar image StrikeMasterz · Jan 07, 2015 at 01:33 AM 0
Share

Edited answer to reflect the comments

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

5 People are following this question.

avatar image avatar image avatar image avatar image avatar image

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


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges