# 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. Commented Aug 23, 2014 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;

• Heheh, Larry would be proud! c2.com/cgi/wiki?LazinessImpatienceHubris
– jzx
Commented Aug 21, 2014 at 11:28
• Note that Unity already provides methods to get the magnitude and squared magnitude of a Vector. Commented Aug 21, 2014 at 15:20
• This produces NaN if no keys are pressed Commented Aug 21, 2014 at 15:34
• @jzx Indeed, we strive to be like the fabled Hobbits. youtube.com/watch?v=G49RUPv5-NU Commented Aug 21, 2014 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? Commented Aug 21, 2014 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. Commented Aug 21, 2014 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. Commented Aug 21, 2014 at 15:24
• I'd clamp to 1 and only multiply with moveSpeed after clamping and possibly merge it with the multiplication by deltaTime. Commented Aug 21, 2014 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... Commented Aug 21, 2014 at 19:43