Double tap mechanics and axis inputs

Hello all,

I am making a 2D sprite-based brawler type game, and I am currently encountering some trouble trying to convert some of my keyboard commands to Xbox controller commands which use GetAxis() instead of GetKeyDown() or GetButtonDown().

I already have a working implementation of a double tap to dash mechanic on my main character, however, it does not convert well into the Xbox control scheme.

The problem lies in the fact that I use GetButtonDown() to detect my keyboard inputs while the controller uses GetAxis(). I have solved a bunch of other problems that deal with this sort of issue but I an completely stumped on how I can make a double tap mechanism work on something that doesn’t work like GetButtonDown().

For further clarification, this is the root of my problem:

When GetButtonDown() is included in conditionals, it fires once, on the frame that the button press was detected and does not continue firing despite the button being held down.
However, Getaxis() acts more like GetButton(), it will fire every single update frame until you let go of the input.

If there is enough interest, I will post the code. Anyone else have similar problems or have helpful tips?

var ButtonCooler : float = 0.5 ; // Half a second before reset
var ButtonCount : int = 0;
function Update ( )
{
if ( Input.GetKeyDown ( KeyCode.X ) ){

      if ( ButtonCooler > 0 && ButtonCount == 1){
         //Has double tapped
      }else{
        ButtonCooler = 0.5 ; 
        ButtonCount += 1 ;
      }
   }

   if ( ButtonCooler > 0 )
   {

      ButtonCooler -= 1 * Time.deltaTime ;
  
   }else{
      ButtonCount = 0 ;
   }
}

This detects whether or not the player has pressed X twice within 0.5 seconds.

Please forgive me if there are any syntax errors, but, otherwise, this should work just fine for you.

Oh, I misinterpreted my brain. Deleted my old answer since it was just wrong anyway. How’s this look?

You can leave this running as a coroutine, or just yank out the stuff in the while-loop and put that in an Update - then you can drop the SendMessages too and hooray.

function TapCheck( axis : String, notify : GameObject ) {
	var lastInput : boolean;
	var tapCount : int;
	var lastTap : float;
	var leeway : float = 0.4; // how fast you have to tap
	var maxtaps : int = 2;
	
	while ( true ) { // contents of this block could go in an Update (sans yield) if desired
		if ( Input.GetAxis(axis) ) {
			// we're on a One input
			// if we WERE on a Zero input, this is an 'edge' - a 'tap'
			if ( !lastInput ) {
				lastTap = Time.time;
				lastInput = true;
				tapCount++;
				if ( tapCount == 1 ) { notify.SendMessage("Tap" + axis); }
				if ( tapCount == 2 ) { notify.SendMessage("DoubleTap" + axis); }
				// etc.
				if ( tapCount == maxtaps ) tapCount = 0;
			}
		} else {
			lastInput = false; // we're on a Zero input
			if ( Time.time - lastTap > leeway ) tapCount = 0; // clear taps if it's been too long
		}
		yield;
	}
}

Try this code it returns a bool so you can set a move bool equal to it. You could use a thershold for the directionalInput.x if you are using a joystick so they dont have to go all the way back to zero.

public bool isRunning = false;
bool firstPress = false;
float pressTime = .25f;
float currentTime = 0;
int axisBeforeZero=0;
int previousAxis = 0;

bool CheckRunning(){
	if(currentTime<=0){//if the player has not provided new input in the time limit reset everything
		axisBeforeZero=0;
		firstPress=false;
	}
	if(directionalInput.x==0){//player is not currently giving movement input...equivalent to releasing the button or axis
		if(previousAxis!=0){//first frame after the axis is released and the player had been moving in a direction
			axisBeforeZero=previousAxis;//keep track of the direction the player had been moving
			previousAxis=0;//set previousAxis to zero
			currentTime=pressTime;//give the player time to complete the double tap
			return(false);
		}else{
			currentTime-=Time.deltaTime;
			return(false);
		}                                                                                                                 
	}else if(directionalInput.x!=0){
		int xDirection=(int)Mathf.Sign(directionalInput.x);//gets the direction the player is currently trying to move
		if(xDirection==previousAxis&&isRunning){//keep running if the player is currently running the same direction
			currentTime-=Time.deltaTime;
			return(true);
		}else if(xDirection==axisBeforeZero&&previousAxis==0){//player has pressed the axis in the same direction within the required time
			previousAxis=xDirection;//set the previous axis for the next frame
			if(firstPress){//the player has already pressed the axis once 
				currentTime-=Time.deltaTime;
				return(true);
			}else{//this is the first time the player has pressed the axis
				firstPress=true;
				currentTime=pressTime;
				return(false);  
			}
		}else if(xDirection!= axisBeforeZero){//the player has changed directions or started moving from zero
			previousAxis=xDirection;
			currentTime=0;
			return(false);
		}else{
			currentTime-=Time.deltaTime;
			return(false);
		}
	}else{//return the current running bool to prevent compiling errors... this stament of code should NEVER RUN
		currentTime-=Time.deltaTime;
		return(isRunning);                                                                                                                                                                                                                                                                           
	}
}