Stamina cooldown

Hi, I’m trying to make a few seconds stop before stamina bar start to fill up again. What should I use for it?

using UnityEngine;
using System.Collections;

public class Staminer : MonoBehaviour {
float stamina=5, maxStamina=5;
float walkSpeed, runSpeed;
CharacterMotor cm;
bool isRunning;

Rect staminaRect;
Texture2D staminaTexture;

// Use this for initialization
void Start () {
cm = gameObject.GetComponent<CharacterMotor> ();
walkSpeed = cm.movement.maxForwardSpeed;
runSpeed = walkSpeed * 4;

staminaRect = new Rect (Screen.width / 10, Screen.height * 9 / 10,
                     Screen.width / 3, Screen.height / 50);
staminaTexture = new Texture2D (1, 1);
staminaTexture.SetPixel (0, 0, Color.white);
staminaTexture.Apply ();
}

void SetRunning(bool isRunning)
{
this.isRunning = isRunning;
cm.movement.maxForwardSpeed = isRunning ? runSpeed : walkSpeed;
}

// Update is called once per frame
void Update () {
if (Input.GetKeyDown (KeyCode.LeftShift))
SetRunning (true);
if (Input.GetKeyUp (KeyCode.LeftShift))
SetRunning (false);

if (isRunning) {
stamina -= Time.deltaTime;
if (stamina < 0) {
stamina = 0;
SetRunning (false);
}

} 
else if (stamina < maxStamina) 
{

stamina += Time.deltaTime;
}

}
	
	

void OnGUI()
{
float ratio = stamina / maxStamina;
float rectWidth = ratio * Screen.width / 3;
staminaRect.width = rectWidth;
GUI.DrawTexture (staminaRect, staminaTexture);
}

}

If I got you right then this is one of the possible ways to do it (also reworked a bit your code):

  //Add this code or just modify needed parts:
        bool isRunning;
        bool StartReloadingStamina = true;
        private const float _waitTime = 2;
        void SetRunning(bool run)
        {
            cm.movement.maxForwardSpeed = run ? runSpeed : walkSpeed;
        }
        IEnumerator Cooldown()
        {
            StartReloadingStamina = false;
            // wait for set amount of time
            yield return new WaitForSeconds(_waitTime);
            StartReloadingStamina = true;
        }
        // Update is called once per frame
        void Update()
        {
            //
            if (Input.GetKeyDown(KeyCode.LeftShift))
            {
                if (stamina > 0)
                {
                    stamina -= Time.deltaTime;
                    isRunning = true;
                }
                else
                {
                    stamina = 0;
                    isRunning = false;
                    StartCoroutine(Cooldown());
                }
            }
            if (Input.GetKeyUp(KeyCode.LeftShift))
            {
                isRunning = false;
                StartCoroutine(Cooldown());
            }
            if (stamina < maxStamina && StartReloadingStamina && !isRunning)
            {
                stamina = Mathf.Clamp(stamina + Time.deltaTime, 0f, maxStamina);
            }
            SetRunning(isRunning);
        }

I haven’t tested it but it should work, moreover I’d edit your code even furthermore, but that won’t give noticeable performance improvement and question wasn’t about it ))

P.S. Just in case I got you wrong - if you want to stop char completely on stamina out then you’ll need to modify this statement “cm.movement.maxForwardSpeed = run ? runSpeed : walkSpeed;” to use third value (e.g. it could be nullable bool “bool?” or byte or… instead of your bool in SetRunning function) and then just assign third value in SetRunning(isRunning) if StartReloadingStamin is true"

P.P.S. Reworked code if I got you right now, as well changed the P.S. section to fit new code.

P.P.P.S. Added cooldown on LShift up if I got you right this time.

You might want to use a Coroutine that handles the stamina bar.

here’s an example with “WaitForSeconds”

You can start a Coroutine, something like this:

public float CooldownTime = 5f;
bool StartReloadingStamina = false;

IEnumerator Cooldown()
	{
		StartReloadingStamina = false;
		// wait for set amount of time
		yield return new WaitForSeconds(CooldownTime);
		StartReloadingStamina = true;
	}

This would imply surrounding the part where you reload the stamina with something like:

if (!StartReloadingStamina) {
	// your stamina reloading code
}

You can start the coroutine when you need it to by using StartCoroutine(Cooldown());

Hope that helps

Hi,

You can use a yield instruction and a coroutine. Here is a little exemple for coloring an object you touch with a raycast for 2 seconds, you should be able to adapt it to your case (you obviously don’t need all the raycast part but il leave it so it is coherent) :slight_smile:

// Called once a frame
	void Update () {
		// Creates a ray from mouse position to world
		// Creates the hit object that will carry hitPoint, hitDistance data
		Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
		RaycastHit hit;
		
		// Takes the coordinates of the hit and set the ray to red + stopping on the gameobject
		if (Physics.Raycast (ray, out hit)) {
			// Display the ray in the scene view if there is no hit (not game view)
			Debug.DrawRay (ray.origin, ray.direction * hit.distance, Color.red);

			// Changes the color of the gameobject touched
			Transform objectHit = hit.transform;

			if(objectHit.tag == "Colorable")
				StartCoroutine(ChangeColor(objectHit));

			return; // Gets out of Update to end the instructions here
		}
		
		// Display the ray in the scene view if there is no hit (not game view)
		Debug.DrawRay (ray.origin, ray.direction * 15, Color.cyan);
		
	}

	IEnumerator ChangeColor(Transform objectToChange){
		objectToChange.gameObject.GetComponent<Renderer>().material.color = Color.green;
		yield return new WaitForSeconds(2);
		objectToChange.gameObject.GetComponent<Renderer>().material.color = Color.white;
	}

using UnityEngine;
using System.Collections;
public class Staminer : MonoBehaviour {
float stamina=5, maxStamina=5;
float walkSpeed, runSpeed;
CharacterMotor cm;
bool isRunning;
Rect staminaRect;
Texture2D staminaTexture;

	public float CooldownTime = 5f;
	bool StartReloadingStamina = false;
	
	
	IEnumerator Cooldown()
	{
		StartReloadingStamina = false;
		// wait for set amount of time
	yield return new WaitForSeconds(CooldownTime);
		StartReloadingStamina = true;
	}
// Use this for initialization
	void Start () {
		cm = gameObject.GetComponent<CharacterMotor> ();
		walkSpeed = cm.movement.maxForwardSpeed;
		runSpeed = walkSpeed * 4;
		staminaRect = new Rect (Screen.width / 10, Screen.height * 9 / 10,
		Screen.width / 3, Screen.height / 50);
		staminaTexture = new Texture2D (1, 1);
		staminaTexture.SetPixel (0, 0, Color.white);
		staminaTexture.Apply ();
	}
	void SetRunning(bool isRunning)
	{
		this.isRunning = isRunning;
	cm.movement.maxForwardSpeed = isRunning ? runSpeed : walkSpeed;
	}
	// Update is called once per frame
	void Update () {
		if (Input.GetKeyDown (KeyCode.LeftShift))
			SetRunning (true);
		if (Input.GetKeyUp (KeyCode.LeftShift))
			SetRunning (false);
		if (isRunning) {
			stamina -= Time.deltaTime;
		if (stamina < 0) {
			stamina = 0;
		SetRunning (false);
		}
	}
		if (stamina < maxStamina)
		{
			if(!StartReloadingStamina)
			{
				stamina += Time.deltaTime;
			}
		}
}
	void OnGUI()
	{
		float ratio = stamina / maxStamina;
		float rectWidth = ratio * Screen.width / 3;
		staminaRect.width = rectWidth;
		GUI.DrawTexture (staminaRect, staminaTexture);
	}
}

Maybe I’m newbie but for me, it should work fine now… But it already doesn’t. Is there anything I made wrong?