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

Looking for feedback on my coroutine code. Trying to prohibit calling more than once.

Discussion in 'Scripting' started by reinfeldx, Feb 20, 2015.

  1. reinfeldx

    reinfeldx

    Joined:
    Nov 23, 2013
    Posts:
    162
    Here is a simple coroutine that calls Translate on an object after a single button press.

    Within Update, if the script gets another button press, it stops the current coroutine and starts another. I am trying to prohibit calling PatrolRight a second time and doubling the Translate speed. Is this the best way to go about doing that?

    Thanks!

    Code (CSharp):
    1. public class PatrolTest5 : MonoBehaviour {
    2.  
    3.     public float speed = 1f;
    4.    
    5.     // Update is called once per frame
    6.     void Update () {
    7.  
    8.         float h = Input.GetAxisRaw ("Horizontal");
    9.        
    10.         if (h > 0 && Input.GetButtonDown ("Horizontal")) {
    11.  
    12.             // Don't allow two coroutines at once.
    13.             StopCoroutine ("PatrolRight");
    14.             StartCoroutine ("PatrolRight");
    15.         }
    16.     }
    17.  
    18.     IEnumerator PatrolRight () {
    19.  
    20.         while (true) {
    21.             transform.Translate (speed * Time.deltaTime, 0, 0);
    22.             yield return null;
    23.         }
    24.     }
    25. }
     
  2. gtzpower

    gtzpower

    Joined:
    Jan 23, 2011
    Posts:
    318
    You could setup a boolean like bHasPatrolRightBeenCalled, that you mark true when you start the coroutine. Then, only start the coroutine if that boolean is false.

    Then again, once you have the boolean, you don't really need the coroutine. You can do your transform.Translate in the Update() function if your boolean is set to true.
    Code (CSharp):
    1. bool bPatrolRight = false;
    2. void Update () {
    3.     float h = Input.GetAxisRaw ("Horizontal");
    4.      
    5.     if (h > 0 && Input.GetButtonDown ("Horizontal")) {
    6.         bPatrolRight = true;
    7.     }
    8.  
    9.     if(bPatrolRight)
    10.         transform.Translate (speed * Time.deltaTime, 0, 0);
    11. }
     
    JoeStrout likes this.
  3. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,840
    Yeah, what @gtzpower said. People are often far too quick to reach for coroutines, which in my experience often cause more grief than they cure. If you can do what you need with a simple bit of logic in Update, just do that.
     
    gtzpower likes this.
  4. reinfeldx

    reinfeldx

    Joined:
    Nov 23, 2013
    Posts:
    162
    I'm surprised to hear that. In my very limited experience with coroutines and Unity, I've found them to be nice solutions that would otherwise require at least as many lines of code to script out with booleans.

    Do you have any specific words of caution against using coroutines or is it just a general feeling?
     
  5. gtzpower

    gtzpower

    Joined:
    Jan 23, 2011
    Posts:
    318
    In my opinion, the logic is easier to follow when it is not in a coroutine, and you aren't really seeing any benefit from the added complexity. I think this thread is actually a perfect example of how things can be simplified without them. The whole problem stems from the fact that even with a coroutine, you still need to script out a boolean to control when you fire off the coroutine.

    Coroutines make sense, for example, when you are waiting on a web server to reply and you don't want to lock up the entire thread in the meantime. They allow you to run blocking calls in a non-blocking fashion. That's about all I personally use them for.
     
  6. gamer_boy_81

    gamer_boy_81

    Joined:
    Jun 13, 2014
    Posts:
    169
    The only little problem with gtzpower's code is that bPatrolRight needs to be set to false.
    That can be done just before the if check :

    Code (CSharp):
    1. bool bPatrolRight = false;
    2. void Update () {
    3.     float h = Input.GetAxisRaw ("Horizontal");
    4.    
    5.     bPatrolRight = false;
    6.  
    7.     if (h > 0 && Input.GetButtonDown ("Horizontal")) {
    8.         bPatrolRight = true;
    9.     }
    10.     if(bPatrolRight)
    11.         transform.Translate (speed * Time.deltaTime, 0, 0);
    12. }
     
  7. gtzpower

    gtzpower

    Joined:
    Jan 23, 2011
    Posts:
    318
    @gamer_boy_81, actually, my suggestion was written to perform as a replacement for the existing code, which does not turn off the horizontal motion once the button is pressed.
     
  8. gamer_boy_81

    gamer_boy_81

    Joined:
    Jun 13, 2014
    Posts:
    169
    aah @gtzpower you're right..sorry for that.