double tap a key to sprint - c#

Looked around the internet for something but I can’t find anything useful for my situation.

So when the user presses d twice or a twice in a the space of 0.5 seconds I want my program to change the players animation and increase speed 4x.

However when I run my game if i press d once for example it automatically changes to the sprint animation and doesn’t increase speed.

Thanks in advance.

using UnityEngine;
using System.Collections;

public class PlayerController : MonoBehaviour {

	public float maxSpeed = 0.5f; //new float variable called maxspeed it equals 10
	public float sprintSpeed = 2f;
	bool facingRight = true; //new bool variable called facingright it equals true
	
	Animator anim;
	Rigidbody2D rb;

	int buttonPresses = 0;
	float buttonPressTimer = 0.5f;



	void Start()
	{
		anim = GetComponent<Animator>();
		rb = GetComponent<Rigidbody2D> ();
	}

	void FixedUpdate()
 {
     float move = Input.GetAxisRaw ("Horizontal"); //how much we are moving
     bool left = Input.GetKeyDown (KeyCode.A);
     bool right = Input.GetKeyDown (KeyCode.D);

     
     if(Input.GetKeyDown (KeyCode.D))
     {
         anim.SetFloat ("Speed", Mathf.Abs (move));        
         rb.velocity = new Vector2 (move * maxSpeed, rb.velocity.y);
         buttonPressTimer -= Time.deltaTime;

         if(Input.GetKeyDown (KeyCode.D) && buttonPressTimer > 0)
         {
             rb.velocity = new Vector2 (move * sprintSpeed, rb.velocity.y);
             anim.SetBool ("isRunning",true);
         }
     }



		if (move > 0 && !facingRight) //if moving left and not facing left
		{
			Flip (); //flip
			anim.SetBool("turning",true);
			anim.SetBool("turning",false);
		}
		else if (move < 0 && facingRight) //if moving to the right and not facing right
		{
			Flip (); //flip
			anim.SetBool("turning",true);
			anim.SetBool("turning",false);
		}
	}

	void Flip()
	{
		facingRight = ! facingRight; // flips the character
		Vector3 theScale = transform.localScale; //flips the local scale
		theScale.x *= -1; //flip the x axis 
		transform.localScale = theScale; //apply all of this back to the local scale
	}

}

The problem is here:

float move = Input.GetAxisRaw ("Horizontal");

For your situation, if you hold the D or A button down, move will always be 1 or -1 respectively. Thats what GetAxisRaw will do when you are using a keyboard. Always.

So naturally, given this code:

         if(move < 0 || move > 0)
         {
             buttonPresses += 1;
             if(buttonPresses == 2)
             {
                 Debug.Log("Sprinting");
                 anim.SetBool("isRunning",true);
                 rb.velocity = new Vector2 (move * sprintSpeed, rb.velocity.y);
             }
         }

Your move variable will always be greater than or less than 0 when you are holding the button down. This means that after 2 frames of holding the button down, your character will be sprinting.

What you need to do:

a)Detect when a player initially presses down the D key (Input.GetKeyDown)

b)Begin the timer

c)Detect when a player presses down the D key again (Input.GetKeyDown)

d)Check to see if the timer has elapsed

e)If the timer has not elapsed, you are sprinting. If the timer has elapsed, you aren’t. Reset the timer to get ready to check again.

Hope this helps, if you have questions let me know.

-Fuego

Try This c# code:

public bool runNow = false; //Main variable to be used
public int noOfTapes = 2; //No of taps
public float tapDelay = 0.5f; //Tap delay
public float runNowTime = 5f; //Set main variable to false after this time

private int dPressed = 0; //No of times d has been pressed in tapDelay
	
void Update ()
{
	if(Input.GetKeyDown(KeyCode.D)){
		dPressed += 1;
	}
	if(Input.GetKeyUp(KeyCode.D)){
		Invoke("SetDPressedToZero", tapDelay);
	}
	if(dPressed > noOfTapes - 1){
		runNow = true;
		Invoke("SetRunNowFalse", runNowTime);
	}	
}
	
void SetDPressedToZero ()
{
	dPressed = 0;
}

void SetRunNowFalse ()
{
   runNow = false;
}

Hope this will help :slight_smile:

What you can do is that anytime the player taps the key d, a coroutine is started, and bool A is set to true. While A is true, pressing d will not start the coroutine and once the coroutine ends, A is false. If d is pressed during the coroutine, bool B becomes true which allows sprinting. Once the key is released, bool B once again becomes false.void Update(){ if (!A) { if (Input.GetButtonDown (KeyCode.D)) { StartCoroutine (CheckSprint ()); } } else { if (Input.GetButtonDown (KeyCode.D)) { B = true; } } if (B) { //sprint } if(Input.GetButtonUp(KeyCode.D){ B = false; } } IEnumerator CheckSprint(){ A = true; yield return new WaitForSeconds(0.5f); A = false; }