Search Unity

What happened here?

Discussion in 'Scripting' started by Cooper37, Jul 8, 2017.

  1. Cooper37

    Cooper37

    Joined:
    Jul 21, 2012
    Posts:
    383
    Hi all! Not to go into much details about what I am trying to accomplish here overall, but I'm messing around with a couple of boolean variables in ways that I have done before, only this time, it's not working. Here's a general summary of the code:

    Code (csharp):
    1.  
    2. public bool canAbility = true;
    3. bool isChiShield = false;
    4. void Update(){
    5.         ...();
    6.         StartCoroutine (ChiShield ());
    7.     }
    8. IEnumerator ChiShield(){
    9.         if (Input.GetButtonDown ("Right Shoulder") && canAbility) {
    10.             canAbility = false;
    11.             isChiShield = true;
    12.         }
    13.         yield return new WaitForSeconds (shieldLasting);
    14.         isChiShield = false;
    15.         yield return new WaitForSeconds (shieldCooldown);
    16.         canAbility = true;
    17.     }
    18.  
    When I press the button, isChiShield will be true and canAbility will be false, then go through a lasting time, then the shield will disappear, then go through a cooldown, then I'll be able to use the ability again. This is not the case. Not only can I not use the ability again, in some cases I can't use it the first time. The bools may turn on or off whenever, like sometimes, isChiShield will become true, and sometimes never! Can someone tell me what's happening?
     
  2. Brathnann

    Brathnann

    Joined:
    Aug 12, 2014
    Posts:
    7,188
    This is a classic issue of calling a coroutine from update.

    So, each frame update starts another copy of the coroutine. Which means, for example, the first coroutine starts, it checks the if statement, then hits the first yield and waits whatever amount of time required. However, during that wait, update is creating more coroutines. So, by the time you hit the button, even though your bools may get set to false and true, a previous coroutine that was yielding at shieldLasting and even another one may be yielding at shieldCooldown, thus when they stop yielding, they may switch your bools back right away.

    You're most likely going to have to check for input in update, then only start the cooldown if you do trigger the ability.
     
  3. Cooper37

    Cooper37

    Joined:
    Jul 21, 2012
    Posts:
    383
    So strange...the explanation makes sense, but what bothers me the most is that I have used this type of code before, and it worked just as fine, but now it suddenly becomes a problem? I know this may seem like a dumb question, but what on earth could make a code work one day, and the exact same code not work the next day??
     
  4. Brathnann

    Brathnann

    Joined:
    Aug 12, 2014
    Posts:
    7,188
    If it was the exact same code(just different variables/method names) then it's hard to say, you may have been lucky or just not noticed the issue. Otherwise, you should have encountered similar problems.

    It's also possible maybe you had a slight variation that made it behave differently.

    I honestly couldn't tell you why and am just guessing. This just tends to be a common issue when starting coroutines from update.

    You might be ok moving the yields and such inside the if statement as well. Since this should only trigger the wait on the coroutine that detects the button push.