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

Help on creating my Stamina System

Discussion in 'Scripting' started by billywafuu, Jul 5, 2017.

  1. billywafuu

    billywafuu

    Joined:
    Jun 30, 2017
    Posts:
    16
    I read similar topic but I'm afraid my mind can't relate to other things, I'm a bit new to Unity to please bear with me. I just need to know your thoughts and comments on where should I start or what I should be learning.

    Summary
    I want to create a Stamina System with a cool down in a short period of time.


    What I did for now
    I am using the ThirdPersonAnimatorController with an UMA Dynamic Character Avatar and it works fine, I can sprint with SHIFT. Now, I decided to create stamina system for it that the player can only run for a short period of time and the stamina will refill again for a short period of time.

    The script
    Code (CSharp):
    1.    
    2. // walk speed multiplier
    3.             m_Move *= 0.5f;
    4.          
    5.             if (Input.GetKey(KeyCode.LeftShift))
    6.             {
    7.        
    8.                 m_Move *= 2;
    9.              
    10.             }
    11.  
    12.             // If the LEFTSHIFT is released, regenerate stamina, I don't know what to do here, a continuous loop maybe
    13.             if (Input.GetKeyUp(KeyCode.LeftShift))
    14.             {
    15.              
    16.             }
    By pressing LEFT SHIFT my character will run, alongside with this I want a timer/or a variable that is decreasing when he is running. I want it to look something like this:

    Code (CSharp):
    1.    
    2. int stamina=100;
    3. // walk speed multiplier
    4.             m_Move *= 0.5f;
    5.          
    6.             if (Input.GetKey(KeyCode.LeftShift))
    7.             {
    8.          if(stamina<=0){
    9.                 m_Move *= 0.5f; // If the stamina is 0 that character will just walk.
    10. }else{
    11. m_Move *=2; // Else, obviously, it will run.
    12. stamina--;
    13. }
    14.              
    15.             }
    16.  
    17.             // If the LEFTSHIFT is released, regenerate stamina, I don't know what to do here, a continuous loop maybe
    18.             if (Input.GetKeyUp(KeyCode.LeftShift)){
    19. RegenerateStaminaOvertime(); // Some function to regenerate stamina to 100.
    20.      
    21.              
    22.             }
    23.  
    24.  
    My main problem
    I don't know how to do it outside the code, maybe put it on another thread that runs separately like if LEFT SHIFT is pressed, another thread will run and will decrease the stamina may be 5 stamina points per seconds which means you can sprint like 20 seconds. But if the LEFT SHIFT is released, vice versa, stamina will recover overtime until it reaches 100. I don't want to do it every frame, or can I instead do it there? I don't know.

    Or, my idea is:

    Code (CSharp):
    1.    
    2. _____________________
    3. [I]code1.cs[/I]
    4. _____________________
    5. bool canRun=true;
    6. // walk speed multiplier
    7.             m_Move *= 0.5f;
    8.          
    9.             if (Input.GetKey(KeyCode.LeftShift))
    10.             {
    11. code2.DecreaseStaminaOvertime();
    12.          if(!canRun){
    13.                 m_Move *= 0.5f; // If the stamina is 0 that character will just walk.
    14. }else{
    15. m_Move *=2; // Else, obviously, it will run.
    16. }
    17.              
    18.             }
    19.  
    20.             // If the LEFTSHIFT is released, regenerate stamina, I don't know what to do here, a continuous loop maybe
    21.             if (Input.GetKeyUp(KeyCode.LeftShift)){
    22. code2.RegenerateStaminaOvertime();
    23.             {
    24.              
    25.             }
    On the other code,

    Code (CSharp):
    1.    
    2. _____________________
    3. [I]code2.cs[/I]
    4. _____________________
    5. int stamina=100;
    6.  
    7. void RegenerateStaminaOvertime(){
    8.  
    9. for(int i=0;i<100;i++){
    10. Wait(1000); // Wait for like 1 second
    11. stamina++;
    12. if(stamina>0){
    13. code1.canRun = true;
    14. }
    15. }
    16.  
    17.  
    18. }
    19.  
    20. void DecreaseStaminaOvertime(){
    21.  
    22. if(stamina==0){
    23. code1.canRun=false;
    24. }
    25.  
    26.  
    27. for(int i=0;i<100;i++){
    28. Wait(1000); // Wait for a second
    29. stamina=stamina-5;
    30. if(stamina<=0){
    31. stamina=0;
    32. code1.canRun=false;
    33. }
    34. }
    35. }
    36.  
    Summary
    I want it something like that, I want to run a separate code while LEFT SHIFT is pressed and if LEFT SHIFT key was released. If there are other suggestions on how I can do it in a better way, It is deeply appreciated, for now I'm currently reading other topics related to my problem now but all helps and comments are again appreciated, thank you so much for the time.
     
  2. Brathnann

    Brathnann

    Joined:
    Aug 12, 2014
    Posts:
    7,144
    Use a coroutine. When shift is released, start the coroutine and do a yield return new WaitForSeconds(1f) or whatever time you need. Then start regenerating in a while loop or something. Just remember you'll want to stop the coroutine if the player starts to sprint mid regen.
     
  3. billywafuu

    billywafuu

    Joined:
    Jun 30, 2017
    Posts:
    16
    Got it, I'll work on it and start studying how coroutine works. Thank you so much, if you have time can you provide a short example using my code above?
     
  4. DigitalMaster37

    DigitalMaster37

    Joined:
    Jun 5, 2013
    Posts:
    5
    I hope this helps. A quick snippet (Haven't had a chance to test)... I kind of threw this together, so I will have to revisit when I leave work.

    Code (CSharp):
    1.  
    2. m_Move *= 0.5f;
    3. cooldown = 1f;
    4.  
    5. if (Input.GetKey(KeyCode.LeftShift))
    6. {
    7.  
    8.        m_Move *= 2;
    9.  
    10. }
    11.  
    12.  // If the LEFTSHIFT is released, regenerate stamina, I don't know what to do here, a continuous loop maybe
    13.  if (Input.GetKeyUp(KeyCode.LeftShift))
    14.  {
    15.        m_Move *= 0.5f;
    16.  
    17.        if (cooldown < 1f)
    18.        {
    19.            StartCoroutine("CooldownMethod");
    20.        }
    21.  }
    22.  
    23. Ienumerator CooldownMethod()
    24.     {
    25.         cooldown += 0.1f;
    26.  
    27.         //the waitforseconds can be however fast you wish for the loop to run
    28.         yield return new waitForSeconds(0.01f);
    29.     }
    30.  
    31.  
     
    billywafuu likes this.
  5. bigmisterb

    bigmisterb

    Joined:
    Nov 6, 2010
    Posts:
    4,221
    For this particular problem, I would not resolve it in a coroutine. These sets of variables are constantly in flux, so because of that, you should handle them in the Update method.

    Code (csharp):
    1.  
    2.     private float modifier = 1;
    3.     private float stamina = 1f;
    4.  
    5.     public float staminaDepletionRate = 2; // seconds until stamina goes from 1 to 0
    6.     public float staminaRegenerationRate = 5; // seconds until stamina goes from 0 to 1
    7.  
    8.     void Update()
    9.     {
    10.         this.modifier = 1f;
    11.         if (Input.GetKey(KeyCode.LeftShift))
    12.         {
    13.             this.modifier = this.stamina == 0 ? 1f : 2f;
    14.             this.stamina = (1 / staminaDepletionRate) * Time.deltaTime;
    15.         }
    16.         else
    17.         {
    18.             this.stamina = (1 / staminaRegenerationRate) * Time.deltaTime;
    19.         }
    20.         this.stamina = Mathf.Clamp01(this.stamina);
    21.     }
    Also, setting the method *= 0.5 and 2, is kind of odd. Just keep a modifier to handle this.

    Code (csharp):
    1.  
    2. transform.Translate(transform.position + transform.forward * this.m_Move * modifier);
    3.