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);
  • 3
    \$\begingroup\$ 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. \$\endgroup\$
    – jhocking
    Commented Aug 23, 2014 at 15:46

3 Answers 3


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


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;

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;

Simpler code is almost always better :E

  • \$\begingroup\$ What does ClampMagnitude do, isn't it the same code as Normalize * Constant in disquise? \$\endgroup\$
    – Kromster
    Commented Aug 21, 2014 at 13:02
  • 2
    \$\begingroup\$ 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. \$\endgroup\$
    – jhocking
    Commented Aug 21, 2014 at 13:20
  • 1
    \$\begingroup\$ +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. \$\endgroup\$ Commented Aug 21, 2014 at 15:24
  • \$\begingroup\$ I'd clamp to 1 and only multiply with moveSpeed after clamping and possibly merge it with the multiplication by deltaTime. \$\endgroup\$ Commented Aug 21, 2014 at 15:38
  • \$\begingroup\$ 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... \$\endgroup\$
    – jhocking
    Commented Aug 21, 2014 at 19:43

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .