I want to make a stamina system for a horror survival game i am making where the player can sprint for around 5 seconds before the stamina running out and having to wait for around 3 seconds before being able to sprint again. Only issue is, I’m fairly new to unity and C# and so am not 100% sure on how to do this for it to work in my game. Any help or pointers would be great.
Below are the two other code files that I have written which cover the movement and the player sprinting.
Main Movement
using System;
using System.Diagnostics.Contracts;
using UnityEngine;
using UnityEngine.InputSystem;
public class Player : MonoBehaviour
{
[SerializeField] float mouseSensitivity = 3f;
[SerializeField] float movementSpeed = 5f;
[SerializeField] float mass = 1f;
[SerializeField] float acceleration = 20f;
public Transform cameraTransform;
public float Height
{
get => controller.height;
set => controller.height = value;
}
public event Action OnBeforeMove;
internal float movementSpeedMultiplier;
CharacterController controller;
internal Vector3 velocity;
Vector2 look;
PlayerInput playerInput;
InputAction moveAction;
InputAction lookAction;
InputAction sprintAction;
void Awake()
{
controller = GetComponent<CharacterController>();
playerInput = GetComponent<PlayerInput>();
moveAction = playerInput.actions["move"];
lookAction = playerInput.actions["look"];
sprintAction = playerInput.actions["sprint"];
}
void Start()
{
Cursor.lockState = CursorLockMode.Locked;
}
// Update is called once per frame
void Update()
{
UpdateGravity();
UpdateMovement();
UpdateLook();
}
void UpdateGravity()
{
var gravity = Physics.gravity * mass * Time.deltaTime;
//determines the vertical velocity
velocity.y = controller.isGrounded ? -1f : velocity.y + gravity.y;
}
Vector3 GetMovementInput()
{
//takes horizontal and vertical input from the keyboard
//var x = Input.GetAxis("Horizontal");
var y = Input.GetAxis("Vertical");
var moveInput = moveAction.ReadValue<Vector2>();
var input = new Vector3();
//input vector by adding the vector pointing from the player forwards, multiplied by 'y'
//'w' and 's' keys
input += transform.forward * moveInput.y;
//input vector by adding the vector pointing from the player, to the right, multiplied by 'x'
//'a' and 'd' keys
input += transform.right * moveInput.x;
//prevents the player from moving faster when moving diagonally
input = Vector3.ClampMagnitude(input, 1f);
input *= movementSpeed * movementSpeedMultiplier;
return input;
}
void UpdateMovement()
{
movementSpeedMultiplier = 1f;
OnBeforeMove?.Invoke();
var input = GetMovementInput();
var factor = acceleration * Time.deltaTime;
velocity.x = Mathf.Lerp(velocity.x, input.x, factor);
velocity.z = Mathf.Lerp(velocity.z, input.z, factor);
controller.Move(velocity * Time.deltaTime);
}
void UpdateLook()
{
var lookInput = lookAction.ReadValue<Vector2>();
look.x += lookInput.x * mouseSensitivity;
look.y += lookInput.y * mouseSensitivity;
look.y = Mathf.Clamp(look.y, -89f, 89f);
//rotates the player object
transform.localRotation = Quaternion.Euler(0,look.x, 0);
//cannot do the same for the 'y' rotation as we need to angle the player object itself
cameraTransform.localRotation = Quaternion.Euler(-look.y, 0, 0);
}
}
Sprinting System
using System;
using UnityEngine;
using UnityEngine.InputSystem;
[RequireComponent(typeof(Player))]
public class PlayerSprinting : MonoBehaviour
{
//will show up in Unity to allow me to easily edit it
[SerializeField] float speedMultiplier = 2f;
Player player;
PlayerInput playerInput;
InputAction sprintAction;
void Awake()
{
//calls component from 'player' file
player = GetComponent<Player>();
//calls component from 'playerInput' file in unity which is naming each input
playerInput = GetComponent<PlayerInput>();
//is calling the new method we made in Unity called sprint
sprintAction = playerInput.actions["sprint"];
}
void OnEnable() => player.OnBeforeMove += OnBeforeMove;
void OnDisable() => player.OnBeforeMove += OnBeforeMove;
void OnBeforeMove()
{
var sprintInput = sprintAction.ReadValue<float>();
if (sprintInput == 0) return;
//combines the players forward vector with the velocity for sprint
//Clamp01 only takes the forward input meaning the player can only sprint when moving forwards
var forwardMovementFactor = Mathf.Clamp01(
Vector3.Dot(player.transform.forward, player.velocity.normalized)
);
var multiplier = Mathf.Lerp(1f, speedMultiplier, forwardMovementFactor);
player.movementSpeedMultiplier *= multiplier;
}
}