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
    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


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
    Aug 21 '14 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
    Aug 21 '14 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\$ Aug 21 '14 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\$ Aug 21 '14 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
    Aug 21 '14 at 19:43

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.