# How to avoid movement speed stacking when multiple keys are pressed?

I've started a new game which requires no mouse, thus leaving the movement up to the keyboard. I have tried to incorporate 8 directions; up, left, right, up-right and so on. However when I press more than one arrow key, the movement speed stacks (http://gfycat.com/CircularBewitchedBarebirdbat). How could I counteract this?

Here is relevant part of my code:

``````var speed : int = 5;

function Update () {
if (Input.GetKey(KeyCode.UpArrow)) {
transform.Translate(Vector3.forward * speed * Time.deltaTime);
} else if (Input.GetKey(KeyCode.UpArrow) && Input.GetKey(KeyCode.RightArrow)) {
transform.Translate(Vector3.forward * speed * Time.deltaTime);
} else if (Input.GetKey(KeyCode.UpArrow) && Input.GetKey(KeyCode.LeftArrow)) {
transform.rotation = Quaternion.AngleAxis(315, Vector3.up);
}
if (Input.GetKey(KeyCode.DownArrow)) {
transform.Translate(Vector3.forward * speed * Time.deltaTime);
}
}
``````
-
tangent: The indentation in your code was a little messed up so I didn't notice at first, but the conditions in your code will prevent most of it from running. Like, if(UpArrow) else if(UpArrow && RightArrow) will never run the 'else' branch. – jhocking Aug 23 '14 at 15:46

Separate your direction selection code from actual movement code.

1. Choose `Direction` by checking which keys are pressed. Store it as a unit (normalized) vector.
2. Multiply your `Direction` with `Speed` and with `DeltaTime`.
3. Apply resulting transform to your object/camera.
-

You need to take the sum of the directions, normalize that, then multiply by the speed.

I tangentially answered this as part of my response to Preventing diagonal movement

Specifically:

``````velX = 0;
velY = 0;

if(keyLeft) velX += -1;
if(keyRight) velX += 1;
if(keyUp) velY += -1;
if(keyDown) velY += 1;

// Normalize to prevent high speed diagonals
length = sqrt((velX * velX ) + (velY * velY ));
if (length != 0)
{
velX /= length;
velY /= length;
}

velX *= speed;
velY *= speed;
``````
-
+1 for sample code. I'm too lazy to write it myself ;) – Kromster Aug 21 '14 at 11:23
Heheh, Larry would be proud! c2.com/cgi/wiki?LazinessImpatienceHubris – jzx Aug 21 '14 at 11:28
Note that Unity already provides methods to get the magnitude and squared magnitude of a Vector. – Assorted Trailmix Aug 21 '14 at 15:20
This produces NaN if no keys are pressed – CodesInChaos Aug 21 '14 at 15:34
@jzx Indeed, we strive to be like the fabled Hobbits. youtube.com/watch?v=G49RUPv5-NU – Pharap Aug 21 '14 at 16:13

The "normalized direction vector" is how this task is usually approached, and how I often do it, but lately I've simply been clamping the resulting movement vector. It usually achieves the same end result and the code is a lot simpler:

``````var moveSpeed = 6.0f;
function Update() {
var movement = Vector3.zero;
movement.x = Input.GetAxis("Horizontal") * moveSpeed;
movement.z = Input.GetAxis("Vertical") * moveSpeed;
movement = Vector3.ClampMagnitude(movement, moveSpeed);
movement *= Time.deltaTime;
transform.Translate(movement);
}
``````

Simpler code is almost always better :E

-
What does `ClampMagnitude` do, isn't it the same code as `Normalize * Constant` in disquise? – Kromster Aug 21 '14 at 13:02
Not quite. "Clamping" a value makes sure it stays within a range/below the maximum, while normalizing sets the value to a constant. With Unity at least, GetAxis() returns slightly accelerating values, giving you a smoother movement. Normalizing the vector overrides that acceleration, while clamping allows the acceleration to happen. It's subtle but looks nicer. The end effect is pretty much the same though. – jhocking Aug 21 '14 at 13:20
+1 for being the only answer written directly in the context of Unity. The API provides all kinds of useful Vector/Quaternion math methods with this sort of situation in mind, no reason to roll your own. – Assorted Trailmix Aug 21 '14 at 15:24
I'd clamp to 1 and only multiply with `moveSpeed` after clamping and possibly merge it with the multiplication by `deltaTime`. – CodesInChaos Aug 21 '14 at 15:38
Does that change gain more than just removing one multiplication operation? Like, does clamping 1 operate differently from clamping 6? wondering what your change does... – jhocking Aug 21 '14 at 19:43