Problem with moving player through a secript by a set distance

I am currently trying to add a sort of "dash"-ability to my sidescroller.

What I try to do, is to let the player press a key where a simple key-press causes the player to move quickly into one direction by a predefined distance. During that dash, the character controller is disabled so the player is not able to cancle the dash itself. after the dash, the character controller is enabled again and the dash ability is disabled, so to say on cooldown. Though the "predefined distance" is what isn't working.

The code for it I have so far is as following. I have a script for choosing the animations and reacting to key Input, this script includes the following in it's Update method ("a" and "d" are set for the Dash). pstats is my object for the variables in the Player-script.

        float dashing = Input.GetAxis ("Dash");

if (Input.GetKey ("a") && pstats.dashUsable)
{
pstats.DashLeft();
}
if (Input.GetKey ("d") && pstats.dashUsable)
{
pstats.DashRight();
}
if (!pstats.dashUsable)
{
dashing = 0.0f;
}


My Playerscript contains:

    public bool dashUsable = true;
public bool dashUsing = false;
public bool attacking = false;

private IEnumerator WaitForNextDash() {
yield return new WaitForSeconds(1.0f);
dashUsable = true;
Debug.Log("WaitForNextDash Done");
}

private IEnumerator WaitForDashToEnd() {
yield return new WaitForSeconds(1.0f);
Debug.Log ("dashUsable being changed");
dashUsable = false;
dashUsing = false;
attacking = false;
controller.enabled = true;
StartCoroutine (WaitForNextDash ());
Debug.Log("WaitForDashToEnd Done");
}

// The two lines below are to create the proper facing-direction for the player
Quaternion targetf = Quaternion.Euler(0, 270, 0);
Quaternion targetb = Quaternion.Euler(0, 90, 0);

public void DashLeft()
{
attacking = true;
dashUsing = true;
controller.enabled = false;
Debug.Log ("Dash-Left-Skill in use");
transform.rotation = Quaternion.Slerp (transform.rotation, targetf, Time.deltaTime * 5000.0f);
transform.position = Vector3.MoveTowards (transform.position, Vector3.right * -100f, 20 * Time.deltaTime);
StartCoroutine (WaitForDashToEnd ());
}

public void DashRight()
{
attacking = true;
dashUsing = true;
controller.enabled = false;
Debug.Log ("Dash-Right-Skill in use");
transform.rotation = Quaternion.Slerp(transform.rotation, targetb, Time.deltaTime * 5000.0f);
transform.position = Vector3.MoveTowards (transform.position, Vector3.right * 100f, 20 * Time.deltaTime);
StartCoroutine (WaitForDashToEnd ());
}


(Sorry for the large blocks of Code, but I thought to better include both)

The problem now is that instead of one button press causing a movement by a set distance... like 100 on the x-axis, the player moves as long as the key is hold. Also, the cooldown for some reason is direction dependant, meaning, if I dash to the right, the cooldown works for the right side, though I can dash to the left directily after without cooldown.

What I am trying to get is to have the WaitForDashToEnd to have a duration that fits the duration of the dash movement itself, I can fix that up as soon as I have the actual dash working. Since the dash movement doesn't work as intented yet, the "stun" during the dash isn't fully functional yet either, but that should more or less fix itself once the dash works.

So... how can I manage to have the dash work as a movement over a predefined distance, no matter how long the key is held?

edit: on a sidenote, during dash, the player is oddly lifted a bit above the ground, is there a way to fix that too? In either case, the dash itself has priority.

• Maybe you want to add the "unity" tag instead of one of the others, that may help raise the attention of the right people! Jun 18 '14 at 15:05
• thanks for the hint xD exchanged the "transform" tag for the "unity" one
– m41n
Jun 18 '14 at 16:29

Firstly you can change Input.GetKey() to Input.GetKeyDown() This ensures that the action only happens during the press and doesn't recall the pstats.DashLeft(); or pstats.DashRight(); Every frame. I think the rest of your logic is sound. but then again my knowledge of unity's C# libraries is a little rusty.

Edit:

I would assume that

transform.position = Vector3.MoveTowards (transform.position, Vector3.right * -100f, 20 * Time.deltaTime);

only happens over one frame. Consider moving it to an update function like

void Update()
{
if(dashUsing)
{
if(dashingRight)
transform.position = Vector3.MoveTowards (transform.position, Vector3.right * -100f, 20 * Time.deltaTime);
else
transform.position = Vector3.MoveTowards (transform.position, Vector3.right * 100f, 20 * Time.deltaTime);
}
}


I always use the update to listen for movement states and then move when the states are true. you can then use coroutines to manage timers for toggling the states and standard methods to do things like calculate the dash to position etc.

hope that helps.

Edit:

Try something like

transform.position = Vector3.MoveTowards (transform.position, Vector3.right * transform.position.x-5f, 20 * Time.deltaTime);

• Did that now, it makes the reaction of the dash work as intended, so allready thanks for that =) Though the dash now is barely any movement, so I think something in the "MoveTowards" is still not really working
– m41n
Jun 18 '14 at 16:29
• Can't check your idea until tomorrow, but it'll be one of the first things I'll do
– m41n
Jun 18 '14 at 19:27
• Okay, that works nicely for the movement itself, though I still have some issues with it... first of all, the animation doesn't play though, though that's the least of the issues. A bigger problem is that no matter at which height I use the dash, it "slides" the character down to the floor instead of moving him straight forward as planned, I guess I'll need something for the other axis in the "Vector3.right" part too, but no idea how
– m41n
Jun 19 '14 at 7:37
• did you move the transform rotation to the update? Jun 19 '14 at 18:15
• the transform.position, as you do in your example code. I did the if-statements a bit differently, but besides that I have it in the update.
– m41n
Jun 19 '14 at 19:02

Going to put this in a new "answer" to prevent it from getting lost in the comments, plus since I hope to get the full solution this way.

So, is it possible to like... define a new vector3 in the way of (pseudocode)

New Vector3 = CurrentLocation + 5 on the X-Axis


And then use that new vector3 on the target for the MoveTowards?

If that's possible, putting both the new vector3 declaration and the MoveTowards into the same part in the Update method, should be a possible solution. Though I am not sure how to really declare a vector3 properly.

So the Main-problem now is to define the vector 3 with the current position of the player and increase the X-axis value.

After that I somehow need a collision with it... not only to avoid moving through walls, but also to have enemies react accordingly when being hit by the dash.