Stamina Bar Help

Hi!

I have a working script for a walking and sprinting mechanism. The thing I was wondering about was how to make a stamina bar that slowly goes down when you’re running and when you’ve stopped running it goes slowly up again.

Here’s my script:

#pragma strict
@script RequireComponent( AudioSource )
 
var walkSounds : AudioClip[];
var runSounds : AudioClip[];
 
var walkAudioSpeed : float = 0.4;
var runAudioSpeed : float = 0.2;
 
private var walkAudioTimer : float = 0.0;
private var runAudioTimer : float = 0.0;
 
var isWalking : boolean = false;
var isRunning : boolean = false;
 
var walkSpeed : float = 8; // regular speed
var runSpeed : float = 20; // run speed
 
var sprintDuration : float = 10.0;
private var sprintTimer : float = 0;
 
private var chCtrl: CharacterController;
private var chMotor: CharacterMotor;
 
function Start()
{
    chCtrl = GetComponent(CharacterController);
    chMotor = GetComponent(CharacterMotor);
}
 
function Update()
{
    SetSpeed();
 
    if ( chCtrl.isGrounded )
    {
       PlayFootsteps();
    }
    else
    {
       walkAudioTimer = 1000.0;
       runAudioTimer = 1000.0;
    }
}
 
function SetSpeed()
{
    var speed = walkSpeed;
 
    if ( Input.GetAxis( "Horizontal" ) || Input.GetAxis( "Vertical" ) )
    {
       if ( Input.GetKey( "left shift" ) || Input.GetKey( "right shift" ) )
       {
         // Running
         isWalking = false;
         isRunning = true;
       }
       else
       {
         // Walking
         isWalking = true;
         isRunning = false;
       }
    }
    else
    {
       // Stopped
       isWalking = false;
       isRunning = false;
    }
 
    // check the sprint timer
    if ( isRunning )
    {
       sprintTimer += Time.deltaTime;
 
       if ( sprintTimer > sprintDuration )
       {
         isRunning = false;
         isWalking = true;
       }
       else if ( chCtrl.isGrounded )
       {
         speed = runSpeed;
       }
    }
    else
    {
       sprintTimer -= Time.deltaTime;
    }
 
    chMotor.movement.maxForwardSpeed = speed;
}
 
function PlayFootsteps()
{
    // Play Audio
    if ( isWalking )
    {
       if ( walkAudioTimer > walkAudioSpeed )
       {
         audio.Stop();
         audio.clip = walkSounds[ Random.Range( 0, walkSounds.Length ) ];
         audio.Play();
         walkAudioTimer = 0.0;
       }
    }
    else if ( isRunning )
    {
       if ( runAudioTimer > runAudioSpeed )
       {
         audio.Stop();
         audio.clip = runSounds[ Random.Range( 0, runSounds.Length ) ];
         audio.Play();
         runAudioTimer = 0.0;
       }
    }
    else
    {
       audio.Stop();
    }
 
    // increment timers
    walkAudioTimer += Time.deltaTime;
    runAudioTimer += Time.deltaTime;
}

Does anyone know how to add this?

I modified the script a little as I never tested it for that answer, and found some strange things happening with the sprint timer going out of bounds.

Now there is a line in the function SetSpeed that clamps the sprint timer :

sprintTimer = Mathf.Clamp( sprintTimer, 0, sprintDuration );

When I say create a normalized value, this means create a value between 0 and 1 that represents the percentage of stamina available. With this percentage, you can modify another value to represent that percentage, eg :

stamina = sprintTimer / sprintDuration;

You can use this value in the width of the GUI bar :

GUI.DrawTexture( Rect( 30, Screen.height - 80, 400 * stamina, 50 ), staminaTexture );

so if stamina is full, the width will be 400; if the stamina is empty, the width will be 0.

but the sprint timer is backwards (max when no stamina, 0 when full stamina), so the stamina line needs to be inverted :

stamina = 1.0 - ( sprintTimer / sprintDuration );

Since I have modified a few things in the original script, here is the complete code with a stamina bar GUI texture included :

//------------------------------//
//  Footsteps.js                //
//  Written by Alucard Jay      //
//  4/11/2014                   //
//------------------------------//

#pragma strict
@script RequireComponent( AudioSource )

public var walkSounds : AudioClip[];
public var runSounds : AudioClip[];

public var walkAudioSpeed : float = 0.4;
public var runAudioSpeed : float = 0.2;

private var walkAudioTimer : float = 0.0;
private var runAudioTimer : float = 0.0;

var isWalking : boolean = false; // these can be private
var isRunning : boolean = false; // these can be private

public var walkSpeed : float = 8; // regular speed
public var runSpeed : float = 20; // run speed

public var sprintDuration : float = 10.0;
private var sprintTimer : float = 0;
private var stamina : float = 0.0;

public var staminaTexture : Texture;

private var chCtrl: CharacterController;
private var chMotor: CharacterMotor;

function Start()
{
	chCtrl = GetComponent(CharacterController);
	chMotor = GetComponent(CharacterMotor);
}

function Update()
{
	SetSpeed();

	if ( chCtrl.isGrounded )
	{
		PlayFootsteps();
	}
	else
	{
		walkAudioTimer = 1000.0;
		runAudioTimer = 1000.0;
	}
}

function SetSpeed()
{
	var speed = walkSpeed;

	if ( Input.GetAxis( "Horizontal" ) || Input.GetAxis( "Vertical" ) )
	{
		if ( Input.GetKey( "left shift" ) || Input.GetKey( "right shift" ) )
		{
			// Running
			isWalking = false;
			isRunning = true;
		}
		else
		{
			// Walking
			isWalking = true;
			isRunning = false;
		}
	}
	else
	{
		// Stopped
		isWalking = false;
		isRunning = false;
	}

	// check the sprint timer
	if ( isRunning )
	{
		sprintTimer += Time.deltaTime;

		if ( sprintTimer > sprintDuration )
		{
			isRunning = false;
			isWalking = true;
		}
		else if ( chCtrl.isGrounded )
		{
			speed = runSpeed;
		}
	}
	else
	{
		sprintTimer -= Time.deltaTime;
	}
	
	sprintTimer = Mathf.Clamp( sprintTimer, 0, sprintDuration );

	chMotor.movement.maxForwardSpeed = speed;

	stamina = 1.0 - ( sprintTimer / sprintDuration );
}

function PlayFootsteps()
{
	// Play Audio
	if ( isWalking )
	{
		if ( walkAudioTimer > walkAudioSpeed )
		{
			audio.Stop();
			audio.clip = walkSounds[ Random.Range( 0, walkSounds.Length ) ];
			audio.Play();
			walkAudioTimer = 0.0;
		}
	}
	else if ( isRunning )
	{
		if ( runAudioTimer > runAudioSpeed )
		{
			audio.Stop();
			audio.clip = runSounds[ Random.Range( 0, runSounds.Length ) ];
			audio.Play();
			runAudioTimer = 0.0;
		}
	}
	else
	{
		audio.Stop();
	}

	// increment timers
	walkAudioTimer += Time.deltaTime;
	runAudioTimer += Time.deltaTime;
}

function OnGUI()
{
	if ( staminaTexture ) // check there is a texture so it doesn't error if not
	{
		GUI.DrawTexture( Rect( 30, Screen.height - 80, 400 * stamina, 50 ), staminaTexture );
	}
}

Create an empty game object that holds the stamina

in the update function use a damp function like Mathf.smoothdamp

smoothdamp( firrst number , target number , external vairable for speed(normally zero) , transition time)

in example : Var1 = Mathf.SmoothDamp (0 , 15 , speed , 5);

after playing , in 5 seconds , 0 reaches 15 . that means every second 3 units are added.

notice , that speed variable should be defined OUTSIDE of the Update function .