Only allow keydown so many times after x amount of seconds.

I have a gameobject that has a constant forward force and I want to allow the player to slow the forward motion but I only want to allow that to happen 3 times then I want the player to have to wait for X amount of seconds before they are able to use the “stall()” function I created.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Controller : MonoBehaviour
{
    public Rigidbody rb;

    public float forwardForce = 2000f;
    public float horizontalForce = 500f;
    public float backForce = 1000f;
    private bool canStall = true;

    // Update is called once per frame
    private void stall()
    {
        rb.AddForce(0, 0, -backForce * Time.deltaTime, ForceMode.Impulse);
    }

    void FixedUpdate ()
    {
        rb.AddForce(0, 0, forwardForce * Time.deltaTime);

        if(Input.GetKey("d"))
        {
            rb.AddForce(horizontalForce * Time.deltaTime, 0, 0, ForceMode.VelocityChange);
        }

        if (Input.GetKey("a"))
        {
            rb.AddForce(-horizontalForce * Time.deltaTime, 0, 0, ForceMode.VelocityChange);
        }
        if (Input.GetKeyDown("s"))
            stall();

        if (rb.position.y < -2f)
        {
            FindObjectOfType<GameManager>().EngGame();
        }
    }
}

Why not just make a counter variable and a timer variable?

If you press stall check the timer, add 1 to the counter if your timer is 10.0f. If the counter reaches 3 then you can set the timer to 0.0f and start counting up to 10.0f again…

Check that your timer is 10.0f and if your timer is not 10, then don’t allow stall().

Then add 1.0f to your timer every second and after it reaches 10.0f, set your counter back to 0.

You build up for a question but don’t follow through.

If you want to do it exactly the way you described, you could keep a counter and fire off a “recharge” coroutine whenever that counter drops to zero.

int stalls = 3;

private void stall()
{
  if (stalls == 0) return;
  rb.AddForce(0, 0, -backForce * Time.deltaTime, ForceMode.Impulse);
  stalls--;
  if (stalls == 0) StartCoroutine(Recharge());
}

private IEnumerator Recharge()
{
  yield return new WaitForSeconds(3);
  stalls = 3;
}

…or if you want to slowly recharge stalls, you can charge up a float value…

float stalls = 3;

private void stall()
{
  if (stalls < 1) return;
  rb.AddForce(0, 0, -backForce * Time.deltaTime, ForceMode.Impulse);
  stalls -= 1;
}

void Update()
{
  stalls = Mathf.Min(3, stalls + Time.deltaTime);
}