Search Unity

Invokerepeating or coroutine?

Discussion in 'Scripting' started by Shablo5, Apr 25, 2020.

  1. Shablo5

    Shablo5

    Joined:
    Mar 2, 2015
    Posts:
    40
    I want to press a button and then something happens every 5 seconds.

    But then I want to press the button again and I want to start another 5 second timer independent of the first, causing the same thing to happen just on its own 5 second timer.

    Then I want to be able to destroy these 5 second timers separately at will, but not all at once.

    Coroutine or invokerepeating?
     
  2. JohnnyA

    JohnnyA

    Joined:
    Apr 9, 2010
    Posts:
    5,041
    You can store a coroutine in a variable and start and stop it at will

    Code (csharp):
    1.  
    2. var myCoRoutine = SomeCoroutine();
    3. StartCoroutine(myCoRoutine);
    4.  
    You could have a collection of these (array, list, queue,etc) if you need more than one.
     
    PraetorBlue likes this.
  3. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,531
    InvokeRepeating only works on string names for the method, and you can only cancel it by string name. Which means you can't cancel an individual invokerepeating if it's the same method.

    Coroutine on the other hand you can have unique handles for each coroutine running, which means you can cancel them uniquely.

    There's other ways to accomplish this as well though... but between those 2 options, I'd go with coroutine. I hate using Invoke and InvokeRepeating just because of the string name thing alone.
     
  4. PraetorBlue

    PraetorBlue

    Joined:
    Dec 13, 2012
    Posts:
    7,909
    Add another vote for coroutines. I don't even know how you would fulfill your requirement of cancelling the individual timers with InvokeRepeating, whereas Coroutines have a clearcut way of doing so.
     
  5. Shablo5

    Shablo5

    Joined:
    Mar 2, 2015
    Posts:
    40
    How do coroutines repeat automatically? Do I just endlessly loop them based on a boolean? Because I know InvokeRepeating just automatically continues each time.
     
    Last edited: Apr 25, 2020
  6. Vryken

    Vryken

    Joined:
    Jan 23, 2018
    Posts:
    2,106
    You can actually use the C#
    nameof
    keyword to get around this, allowing you to directly pass the name of the method by reference instead of a string:
    Code (CSharp):
    1. void SomeMethod() {}
    2.  
    3. Invoke(nameof(SomeMethod), 1f);
    4. InvokeRepeating(nameof(SomeMethod), 1f, 1f);
     
    harlandpj likes this.
  7. Shablo5

    Shablo5

    Joined:
    Mar 2, 2015
    Posts:
    40
    But what if the name of the method is the same method Everytime ?
     
    lordofduct likes this.
  8. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,531
    That only saves you having to use a string explicitly. It's still a string.

    It doesn't resolve the "Which means you can't cancel an individual invokerepeating if it's the same method." part of my statement. If I do this:
    Code (csharp):
    1.  
    2. void SomeMethod() {}
    3.  
    4. IEnumerator Start()
    5. {
    6.     InvokeRepeating(nameof(SomeMehtod), 1f, 1f);
    7.     InvokeRepeating(nameof(SomeMethod), 2f, 0.5f);
    8.     yield return WaitForSeconds(30f);
    9.     /CancelInvoke(nameof(SomeMethod));
    10. }
    11.  
    Which InvokeRepeating gets cancelled?

    BOTH!

    But what if I want to cancel just the first one? And leave the 2nd one running?

    This is what OP needed... the ability to uniquely stop an individual invokerepeating.
     
  9. Vryken

    Vryken

    Joined:
    Jan 23, 2018
    Posts:
    2,106
    Yes, I know.
    Coroutines are definitely what the OP need here and should be used almost exclusively over Invoke/InvokeRepeating.
    I just wanted to share that bit of information about the
    nameof
    keyword.
     
    harlandpj likes this.
  10. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,531
    Thing is nothing of what I said implied I didn't know what 'nameof' is. My statement remains exactly the same.

    And if this was for the edification of OP... then why not direct it at OP instead of me?
     
  11. Vryken

    Vryken

    Joined:
    Jan 23, 2018
    Posts:
    2,106
    I thought when you stated that you didn't like using these methods because of string names alone, it meant that you were using them like this...
    Code (CSharp):
    1. void SomeMethod() {}
    2. Invoke("SomeMethod", 1f);
    ...Which makes it hard to refactor/rename.
    I'm sorry if I told you what you already know.

    I didn't have anything to direct to the OP because their question was already answered: use a coroutine.
     
    Last edited: Apr 25, 2020
  12. Shablo5

    Shablo5

    Joined:
    Mar 2, 2015
    Posts:
    40
    How do coroutines repeat automatically? Do I just endlessly loop them based on a boolean? Because I know InvokeRepeating just automatically continues each time.
     
  13. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,531
    Code (csharp):
    1. IEnumerator LoopingCoroutine(float delay, interval)
    2. {
    3.     if (delay > 0f) yield return new WaitForSeconds(delay);
    4.  
    5.     var waithandle = new WaitForSeconds(interval);
    6.     while(true)
    7.     {
    8.         //do stuff
    9.  
    10.         yield return waitInterval;
    11.     }
    12. }
    Heck you could generalize this further like so:

    Code (csharp):
    1. public static class CoroutineHelper
    2. {
    3.  
    4. public static IEnumerator InvokeRepeating(System.Action callback, float delay, float interval)
    5. {
    6.     if (delay > 0f) yield return new WaitForSeconds(delay);
    7.  
    8.     var waithandle = new WaitForSeconds(interval);
    9.     while(true)
    10.     {
    11.         callback();
    12.         yield return waitInterval;
    13.     }
    14. }
    15.  
    16. }
    And call as:
    Code (csharp):
    1. var handle = StartCoroutine(CoroutineHelper.InvokeRepeating(() => {
    2.     Debug.Log("HELLO WORLD");
    3. }, 1f, 2f));
    then when you want to stop just call StopCoroutine(handle)
     
  14. JohnnyA

    JohnnyA

    Joined:
    Apr 9, 2010
    Posts:
    5,041
    @lordofduct - @Vryken was replying to your quote because what they were adding was relevant to that.

    It wasn't a conflicting piece of information, but a useful and relevant tip. I think it would have been worse to reply to the OP becasue that is suggesting it as a solution which it is not.

    EDIT: For readability, correcting assumed gender pronouns, and to remove implied hostility :)
     
    KiddUniverse likes this.
  15. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,531
    I disagree that it was relevant. Especially since Vryken even stated they misunderstood my post by assuming I meant one thing, when I did not. And that it was specifically directed at me based on that assumption.

    It'd be like if I said: "Because your name is Sean, it is required to spell your name using at least an S and an N." And they responded, "You can also spell it Shaun". My statement is still correct, and the only reason to say it is because you assumed my only mentioning Sean means I don't know Shaun is an alternative spelling.

    It may be a useful tip for someone, but if it was just a general tip there's no need to direct it explicitly at me.

    Though I fail to see how continuing this semantic debate is useful to the topic at hand.
     
    Last edited: Apr 26, 2020