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. We are updating our Terms of Service for all Unity subscription plans, effective October 13, 2022, to create a more streamlined, user-friendly set of terms. Please review them here:
    Dismiss Notice
  3. Have a look at our Games Focus blog post series which will show what Unity is doing for all game developers – now, next year, and in the future.
    Dismiss Notice
  4. Join us on Thursday, September 29, for a day with Unity's SRP teams here on the forum or on Reddit, and discuss topics around URP, HDRP, and the Scriptable Render Pipeline in general.
    Dismiss Notice

InvokeRepeating/CancelInvoke not working

Discussion in 'Scripting' started by BLACKHAWK4547, Sep 23, 2022 at 12:55 AM.

  1. BLACKHAWK4547


    Mar 24, 2020
    so some background on what im doing
    im trying to make a stamina bar that when the player runs it depletes "current stamina" from the "max stamina" and over time the "currently attainable stamina" depletes as well passively. this all works but now I want it so that when the player runs the "currently attainable stamina" will deplete faster than the passive stamina depletion.
    the way ive set this up is by having a player controller script and a stamina bar script, when you press left shift down it gets stamina bar script then invokes the function to deplete it and sets a bool to true that activates something else, and then i have an if statement in my update function stating that if that bool is false cancel the invoke but it dosent despite having a debug log telling me that its getting past that.
    am i using this wrong or dose anyone have any other suggestions on how to approach this ? i am still new enough to coding btw
    Code (CSharp):
    1. void HandleRunInput()
    2.     {
    3.         if(Input.GetKeyDown(KeyCode.LeftShift))
    4.         {
    5.             isRunning = true;
    6.             Sb.InvokeRepeating("GettingTiredStaminaDepleation", 1.0f, 1.0f);
    7.             Debug.Log("Invoked");
    8.         }
    9.         if (Input.GetKeyUp(KeyCode.LeftShift))
    10.         {
    11.             isRunning = false;
    12.         }
    13. }
    Code (CSharp):
    1. void Update()
    2.     {
    3.         if (isRunning == false)
    4.         {
    5.             CancelInvoke("GettingTiredStaminaDepleation");
    6.             Debug.Log("Invoke Cancel");
    7.         }
    8.     }
    side note i have tried cancelInvoke without the string name as well and i have tried putting it in the Input.GetKeyUp statement but still no success
  2. spiney199


    Feb 11, 2021
    Firstly, you didn't need to make another thread with the same problem. You could have continued on from your previous thread.

    Invoke, InvokeRepeating, etc, are pretty old functions that are from the early days of Unity. They're kind of bad practice these days and it's best to not get into the habit of using them.

    It'd be much easier to just increase/decrease your stamina depending on whether you're running or not in an update loop:
    Code (CSharp):
    2. //in player controller
    3. public void Update()
    4. {
    5.     if (Input.GetKeyDown(KeyCode.LeftShift))
    6.     {
    7.         staminaBar.isRunning = true; //give your values descriptive names
    8.     }
    10.     if (Input.GetKeyUp(KeyCode.LeftShift))
    11.     {
    12.         staminaBar.isRunning = false;
    13.     }
    14. }
    16. public class StaminaBar : Monobehaviour
    17. {
    18.     public bool isRunning = false;
    20.     private void Update()
    21.     {
    22.         if (isRunning)
    23.         {
    24.             //decrease stamina
    25.         }
    26.         else
    27.         {
    28.             //increase stamina
    29.         }
    30.     }
    32. }
    This of course doesn't show how to prevent or stop running when stamina runs out, but that's something for you to learn as you go.
  3. BLACKHAWK4547


    Mar 24, 2020
    oh sorry makes sense i probably should have continued on the same thread its just this is a different issue im having on the same script. i also didn't realise invoke was bad practice if that's the case can you point me in the right direction for what i want to achieve, i can probably explain this a little better.
    the stamina bar is recording 3 values one is the max stamina one is displaying how much of that stamina is currently being used and the other is how much can be recharged (currently obtainable stamina) i have a system that depletes the currently obtainable stamina passively at a slow rate but now i want a new condition to deplete it slightly faster when the player starts running and then stop when they aren't running. The way i thought of doing this was by having it tick down by 1 every 2 seconds the player is running and when they stop running that stops. with the bit of code i have now when you run it ticks down by 1 every 2 second but cancel invoke docent stop the invoke and then if i keep pressing the shift button the invoke stacks.
    i have tried it the way you've shown but that depletes it way too fast and ive tried an IEnumerator but that also stacks and depletes it way too fast.
    so is there a better way of ticking down the int (currently obtainable stamina) by 1 every 2 seconds when the player is running
  4. spiney199


    Feb 11, 2021
    Then just... decrease it less? Use a value of a magnitude that you can decrease over a reasonable time. And don't use int, use a float here.

    A float of value 1 would take 1 second to reduce to zero if you decreased it by Time.deltaTime each Update.