Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

I can't get co routines to work c#

Discussion in 'Scripting' started by Dazz500, Jan 11, 2015.

  1. Dazz500

    Dazz500

    Joined:
    Nov 13, 2014
    Posts:
    64
    Hi all, right I'm trying to use co routines so I can have some script running about every 30 seconds. It either seems to get called every frame or not at all.
    So I went to the unity documentation page for co routines and copied & pasted a example from there & I get the same thing.

    This is just after Update
    Code (csharp):
    1.  
    2. IEnumerator WaitAndPrint() {
    3.  yield return new WaitForSeconds(5);
    4.  print("WaitAndPrint " + Time.time);
    5.  }
    6.  
    7.  
    8. IEnumerator Example() {
    9.  print("Starting " + Time.time);
    10.  yield return WaitAndPrint();
    11.  print("Done " + Time.time);
    12.  }
    13.  
    14.  
    This doesn't get called once.

    If I try and put yield return waitandprint in update I get this error
    Assets/pool.cs(109,14): error CS1624: The body of `pool.Update()' cannot be an iterator block because `void' is not an iterator interface type


    I also tried some other unity examples, no luck there either.

    I haven't got a clue what Im doing wrong, any help appreciated
     
  2. cmcpasserby

    cmcpasserby

    Joined:
    Jul 18, 2014
    Posts:
    315
    You have to use StartCoroutine() to run them so something like
    StartCoroutine(WaitAndPrint());
     
  3. Dazz500

    Dazz500

    Joined:
    Nov 13, 2014
    Posts:
    64
    Thanks
    ok I've put that in the update - it waits then once it's called it keeps calling it every frame. Hmm not sure what I'm doing here
     
  4. cowtrix

    cowtrix

    Joined:
    Oct 23, 2012
    Posts:
    318
    1. IEnumerator WaitAndPrint() {
    2. yield return new WaitForSeconds(5);​
    3. print("WaitAndPrint " + Time.time);​
    4. print("Done " + Time.time);​
    5. }


    6. void Example() {
    7. print("Starting " + Time.time);​
    8. StartCoroutine(WaitAndPrint());​
    9. }
    To expand a little more on that: StartCoroutine dispatches the function to the coroutine processor. You can't keep some kind of handle on it through Example() (well, okay, you can, but considering you're starting out with this, K.I.S.S.). You can't treat a coroutine call as a simple function call though, they are very different things.
     
  5. Crayz

    Crayz

    Joined:
    Mar 17, 2014
    Posts:
    192
    Update() is called every frame, so you're starting a new Coroutine in every frame. Place StartCoroutine() in Start(), or use conditionals in Update() so it can only be called once and when it is needed.
     
  6. Dazz500

    Dazz500

    Joined:
    Nov 13, 2014
    Posts:
    64
    I just get

    error CS1525: Unexpected symbol `<internal>'

    on Lines 2,3 & 4
     
  7. cmcpasserby

    cmcpasserby

    Joined:
    Jul 18, 2014
    Posts:
    315
    Also if it is something that is going on all the time why not just do it in the update loop using conditionals and Time.deltaTime?
     
  8. Dazz500

    Dazz500

    Joined:
    Nov 13, 2014
    Posts:
    64
    I thought the whole point of co routines is so they can be repeated but not every frame. I suppose I could use the Time.deltaTime but I'm going to need to use co routines sooner or later so thought I might as well start using them now.

    I tried it again, I put the start coroutine line in start and it gets called once only. If I put it in update it does wait for the specified time but then repeats every frame. Obviously theres something I'm missing just don't know what. I would have thought using the example from the official unity page wouldn't have given me any problems. Guess I'll just have to keep reading & trying.

    Code (csharp):
    1.  
    2. StartCoroutine (WaitAndPrint());
    3.  
     
  9. Sbizz

    Sbizz

    Joined:
    Oct 2, 2014
    Posts:
    250
    Can we have your entire script (I'm not sure of what you have right now) ?
     
    Dantus likes this.
  10. GregMeach

    GregMeach

    Joined:
    Dec 5, 2012
    Posts:
    249
    Start here (or the numerous YouTube tuts)
     
  11. cmcpasserby

    cmcpasserby

    Joined:
    Jul 18, 2014
    Posts:
    315
    Also if you need it to run something every few seconds why are you letting the coroutine die and re running it, why not use a while loop in it
     
  12. Dazz500

    Dazz500

    Joined:
    Nov 13, 2014
    Posts:
    64
    @ cmcpasserby - I'm just using the time.deltatime to run the code every 20 seconds, I'm sure I'm going to need co routines in the future so I'll be reading up on them but for now what I've done is sufficient, thanks for the replys.

    @ GregMeach - Thanks I've already seen that video but I'll have another look in more detail.
     
  13. TheSniperFan

    TheSniperFan

    Joined:
    Jul 18, 2013
    Posts:
    712
    I know of no scenario where you really need coroutines. Not a single one.
    Nothing you couldn't do within Update with a bit of logic.
     
  14. cowtrix

    cowtrix

    Joined:
    Oct 23, 2012
    Posts:
    318
    :rolleyes:
     
    GregMeach likes this.
  15. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,487
    You can actually make your Start() function into a simple coroutine like so:

    Code (csharp):
    1.  
    2.     IEnumerator Start()
    3.     {
    4.         for (int i = 0; i < 5; i++)
    5.         {
    6.             // <WIP> Do Something Here...
    7.             yield return new WaitForSeconds( 1.0f);
    8.         }
    9.         Destroy(this);
    10.     }
    11.  
    I use the above pattern for scripts that run for a certain lifetime and then are over with, fire-and-forget type things.

    NOTE: I threw in the Destry() call at the bottom on the script. If you want to Destroy the entire game object you would use Destroy(gameObject) obviously. This kills the game object.

    The main caveat is, MAKE SURE YOU YIELD! If you do this:

    Code (csharp):
    1.  
    2. while(true)
    3. {
    4. // <Do Things>
    5. }
    6.  
    You will be very unhappy because Unity will lock up.
     
  16. TheSniperFan

    TheSniperFan

    Joined:
    Jul 18, 2013
    Posts:
    712
    Are you trying to say anything?
     
  17. cowtrix

    cowtrix

    Joined:
    Oct 23, 2012
    Posts:
    318
    Interesting! I wasn't aware of this functionality.

    Oh, just trying to figure out if you were joking or not. You should be avoiding Update() like the plague.
     
  18. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,487
    Assuming your statement is serious, I have no idea where this "avoid using Update()" meme got started but there is nothing wrong with using Update() to do something every frame. That is precisely what it is for.

    If you make a coroutine that does something and yields for one frame, and do the same amount of work in an Update() call, you will see exactly zero performance difference for any reasonable amount of game objects that you could ever conceive of having.
     
  19. cowtrix

    cowtrix

    Joined:
    Oct 23, 2012
    Posts:
    318
    I completely agree and I'm unsure what your point is, but my point was that you should minimize processing in Update(). It was specifically in response to:

    Which would imply that operations that are not needed every frame should still be put into Update() with conditionary logic. Which is just awful. So I suppose what I mean by "avoid Update() like the plague" is "minimize per-frame operations as much as you can".
     
  20. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,487
    Coroutines and a simple per-frame update are simply two tools. Use the right tool for the job. Each has its place.
     
    GregMeach likes this.
  21. TheSniperFan

    TheSniperFan

    Joined:
    Jul 18, 2013
    Posts:
    712
    Sorry, but where have you heard this nonsense?
    Putting calculations in coroutines won't magically make them less expensive. You could even make a point for the opposite case, considering how managing coroutines causes additional overhead, whereas Update get's called regardless anyway.
    That's not the point though. If some code causes you problems from within Update, it will cause the same problems from within coroutines.

    The is a good reason why I don't use coroutines (anymore). I'm probably coming from a different angle than you. I am maintaining a complex save system for Unity 5. Resumable coroutines are a PITA and have some dodgy behavior, that you can't fix.

    You'd use exactly the same conditional logic to determine whether to run the coroutine or not.
    On top of that, it's not "just awful". Unless you write some terrible, terrible code, conditional logic is dirt-cheap.
     
  22. CodeMonke234

    CodeMonke234

    Joined:
    Oct 13, 2010
    Posts:
    181
    A few things to consider....

    Invoke and invokerepeating awesome - simpler than coroutines
    http://docs.unity3d.com/ScriptReference/MonoBehaviour.InvokeRepeating.html

    Both coroutines and invoke make your code more readable - putting boatloads of conditional state code in update does not scale.

    Using update for logic that must occur every frame is fine - just not for logic that doesn't need to be evaluated every frame.
     
    GregMeach likes this.
  23. Crayz

    Crayz

    Joined:
    Mar 17, 2014
    Posts:
    192
    I don't think its been mentioned yet here, and probably not necessary for op's situation, but starting an infinite loop in the main thread will cause your process to become unresponsive, though the code will continue to execute and still have opportunity to break out of the loop.

    Code (csharp):
    1. float loopTime = Time.time + 5f;
    2.  
    3. while(Time.time  <= loopTime)
    4. {
    5.      // Process remains unresponsive for 5 seconds while loop executes
    6. }
    However you can use System.Threading and execute loops without your process locking up.

    Code (csharp):
    1. using System.Threading;
    2.  
    3. object myObj = new object();
    4.  
    5. Thread _t = new Thread(new ParameterizedThreadStart(SomeFunction));
    6. _t.Start(myObj);
    7.  
    8. void SomeFunction(object obj)
    9. {
    10.      float loopTime = Time.time + 5f;
    11.  
    12.      while(Time.time  <= loopTime)
    13.      {
    14.           // Process remains responsive for 5 seconds while loop executes
    15.      }
    16.      Thread.CurrentThread.Abort();     // Aborts thread when loop has finished
    17. }
    Executing code outside of the main thread does have its limitations though