- Home /
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);
}
}
Answer by DoTA_KAMIKADzE · Apr 01, 2015 at 12:33 PM
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.
Answer by Notter · Apr 01, 2015 at 12:33 PM
You might want to use a Coroutine that handles the stamina bar.
here's an example with "WaitForSeconds" http://docs.unity3d.com/ScriptReference/Coroutine.html
Answer by florianveltman · Apr 01, 2015 at 12:50 PM
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
Answer by KdRWaylander · Apr 01, 2015 at 11:59 AM
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) :)
// 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;
}
Answer by SemiRomi · Apr 02, 2015 at 05:26 AM
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?
First of all - you never start your Cooldown() function in your code.
Secondly - check out my example to understand the idea, then you can implement there your coroutine Cooldown() and then try to think yourself how to reduce amount of code used per Update - the less complex the better it will be, you won't notice huge performance boost but if you'll think in this way in whole your project then you will.
P.S. Well I'll just update my code in a while, if I got what you want now then it will work as you want, if not just let me know what behavior you need exactly.
P.P.S. Ok done, check it out if that isn't what you want let me know.
using UnityEngine;
using System.Collections;
public class Sta$$anonymous$$er : $$anonymous$$onoBehaviour {
float sta$$anonymous$$a=5, maxSta$$anonymous$$a=5;
Rect sta$$anonymous$$aRect;
Texture2D sta$$anonymous$$aTexture;
public float CooldownTime = 5;
bool StartReloadingSta$$anonymous$$a = true;
IEnumerator Cooldown()
{
StartReloadingSta$$anonymous$$a = false;
// wait for set amount of time
yield return new WaitForSeconds(CooldownTime);
StartReloadingSta$$anonymous$$a = true;
}
// Use this for initialization
void Start () {
sta$$anonymous$$aRect = new Rect (Screen.width / 10, Screen.height * 9 / 10, Screen.width / 3, Screen.height / 50);
sta$$anonymous$$aTexture = new Texture2D (1, 1);
sta$$anonymous$$aTexture.SetPixel (0, 0, Color.white);
sta$$anonymous$$aTexture.Apply ();
}
// Update is called once per frame
void Update () {
if (Input.Get$$anonymous$$ey($$anonymous$$eyCode.LeftShift) && Input.Get$$anonymous$$ey($$anonymous$$eyCode.W))
{
if (sta$$anonymous$$a > 0)
{
sta$$anonymous$$a -= Time.deltaTime * 2;
}
else
{
sta$$anonymous$$a = 0;
StartCoroutine(Cooldown());
gameObject.GetComponent<Character$$anonymous$$otor>().movement.maxForwardSpeed = 6;
}
}
if (sta$$anonymous$$a < maxSta$$anonymous$$a && StartReloadingSta$$anonymous$$a)
{
sta$$anonymous$$a = $$anonymous$$athf.Clamp(sta$$anonymous$$a + Time.deltaTime, 0f, maxSta$$anonymous$$a);
}
}
void OnGUI()
{
float ratio = sta$$anonymous$$a / maxSta$$anonymous$$a;
float rectWidth = ratio * Screen.width / 3;
sta$$anonymous$$aRect.width = rectWidth;
GUI.DrawTexture (sta$$anonymous$$aRect, sta$$anonymous$$aTexture);
}
}
I've changed the code a bit. Hmm... It works fine now, but only when sta$$anonymous$$a = 0. I'll try to set it for sta$$anonymous$$a > 0 now :D Thank You for Your help too :D
You're jocking right? $$anonymous$$y code is the first one on this page, find it by my username.
P.S. And in the code you provided above you just set max speed once and forever to 6 when you run out of sta$$anonymous$$a while holding LShift+W.
I know, cuz I saw that code You edited. And bout this max speed, I just used in another script changing speed by shift + w, so it works fine like this. But hmm... I'm trying to solve the problem with StartCoroutine when sta$$anonymous$$a bar isn't fully empty. And now I'm thinking about how to make it...
Check my code once again, added Cooldown if player stopped running even if sta$$anonymous$$a has not run out if that is what you want.
Your answer
Follow this Question
Related Questions
Reducing an integer by X per second 1 Answer
Why aren't these numbers going down by 1. 1 Answer
Trouble with Stamina controller 1 Answer
Why does it give me an error in this small java script for sprint? 1 Answer
how do I set the Animations For running and walking properly to match the stamina bar? 1 Answer