Making an effective Airdash

I’ve just recently started using Unity3D and it’s truly, for lack of better words, awesome. It’s almost like a toy box with an unlimited amount of toys.

Anyway, I’ve been through a few tutorials on 2D platforming controls, and I’ve applied what I know so far on an innocent cube. But I wanted to add something else to it: an Airdash. I have somewhat of an idea on how to implement it, but my idea currently results in the cube hovering in the air for as long as the WaitForSeconds last.

What I basically want to do is have it to where JS sees that I am FIRST holding either left or right and when I press a dash button (X), I go in the held direction for a certain amount of time without being affected by gravity or letting go of the button. Imagine a Megaman X2 or Marvel vs Capcom airdash.

Excuse the code for being messy. I plan on fixing it once I have the basics implimented.

Any ideas or corrections would be most helpful. Thank you.

@System.NonSerialized
private var jumpCount : int = 0;

@System.NonSerialized
private var gravity : float = 35.0;

@System.NonSerialized
private var gravenabled : boolean = true;

@System.NonSerialized
private var inAir : boolean = false;

@System.NonSerialized
private var velocity : Vector3;

@System.NonSerialized
private var walkSpeed : float = 7.0;

@System.NonSerialized
private var runSpeed : float = 15.0;

@System.NonSerialized
private var jumpSpeed : float = 7.0;

@System.NonSerialized
private var airdashcount : int = 0;

@System.NonSerialized
private var airdashspeed : float = 40.0;

class characjump {

@System.NonSerialized
var height: float = 30.0;

@System.NonSerialized
var doubleheight: float = 15.0;

@System.NonSerialized
var verticalSpeed: float = 0.0;
}

var charjump : characjump;

private var moveDirection : Vector3 = Vector3.zero;

var controller : CharacterController;
controller = GetComponent(CharacterController);

function Move (){
var h = Input.GetAxisRaw("Horizontal");
var v = Input.GetAxisRaw("Vertical");
var airdash: boolean = false;
var doubletap: float = 0.5;
var lastTime: float = 0.0;
var running: boolean = false;
var moving: boolean = false;
var canControl: boolean = true;

var isMoving = Mathf.Abs(h) == 1;



if (controller.isGrounded)
{
if (Input.GetKey(KeyCode.DownArrow)||Input.GetKeyUp(KeyCode.LeftArrow) || Input.GetKeyUp(KeyCode.RightArrow))
{
moveDirection.x = 0;
}
else if (Input.GetKey(KeyCode.LeftArrow) || Input.GetKey(KeyCode.RightArrow))
{
moveDirection.x = h;
moveDirection = transform.TransformDirection(moveDirection);
moveDirection.x *= (running ? runSpeed : walkSpeed);
}
}

else
{
if (Input.GetKey(KeyCode.X) && !controller.isGrounded && isMoving)
{
airdash = true;
}

if (airdash && airdashcount == 0){

gravenabled = false;
moveDirection.x = h;
moveDirection.y = 0;
moveDirection = transform.TransformDirection(moveDirection);
moveDirection.x *= airdashspeed;

yield WaitForSeconds(.3);

gravenabled = true;
airdashcount = 1;
}

else
{
moveDirection.x = h;
moveDirection = transform.TransformDirection(moveDirection);
moveDirection.x *= jumpSpeed;
}
}
}

function Jump ()
{
var jump = Input.GetKeyDown(KeyCode.Z);
var fastfall = Input.GetKeyDown(KeyCode.DownArrow);
if(!controller.isGround)
{
inAir = true;
}

if(jump)
{

jumpCount +=1;


if (jumpCount == 0)
{
moveDirection.y = charjump.height;
}
else if (jumpCount == 1)
{
gravenabled = true;
moveDirection.y = charjump.doubleheight;
gravity = 35.0;
}
}

if (inAir && controller.velocity.y <= 0.0){
	if (fastfall)
	{
	gravity = 120.0;
	audio.Play();
	}

}

}

function Gravity (){
if (gravenabled)
{
moveDirection.y -= gravity * Time.deltaTime;
}
}

function Update (){


Jump();
Move();

if (controller.isGrounded)
{
jumpCount = 0;
gravity = 35.0;
airdash = false;
gravenabled = true;
airdashcount = 0;
}

Gravity();
controller.Move(moveDirection * Time.deltaTime);

}


@script RequireComponent (CharacterController)
@script RequireComponent(AudioSource)

NOTE –

as a rule, if a variable is private, it is pointless to mark it as System.NonSerialized. in your first ten lines you can delete those where you have private.

Within an explicit class definition, I think it’s always pointless to use System.NonSerialized, because those are never shown in the inspector anyway.

Gravity - one way to “turn off” an object being affected by gravity temporarily, is, use the very handy ConstantForce component. (Look in menus, component, physics.)

“What I basically want to do is have it to where JS sees that I am FIRST holding either left or right and when I press a dash button (X)”…

do you specifically want the key AA to be pressed BEFORE the key BB?

Input.GetKey 
Returns true WHILE the user holds down the key...
Input.GetKeyDown 
Returns true DIRING THE FRAME the user starts pressing DOWN the key...

I guess, you could just use those like this:

if GetKey(AA)  // ok so AA must be down
  if  GetKeyDown(BB) // AND this must be FIRST frame of BB down
    if ! GetKeyDown(AA) // AND this must NOT be FIRST frame of AA down!

I suppose that should work! Normally you’d have booleans keeping track of what the hell is going on, but there’s no reason that should work to let you press forwards.