Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

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);
    }
}
share|improve this question
3  
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 at 15:46

3 Answers 3

up vote 13 down vote accepted

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.
share|improve this answer

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;
share|improve this answer
1  
+1 for sample code. I'm too lazy to write it myself ;) –  Krom Stern Aug 21 at 11:23
3  
Heheh, Larry would be proud! c2.com/cgi/wiki?LazinessImpatienceHubris –  jzx Aug 21 at 11:28
3  
Note that Unity already provides methods to get the magnitude and squared magnitude of a Vector. –  Assorted Trailmix Aug 21 at 15:20
    
This produces NaN if no keys are pressed –  CodesInChaos Aug 21 at 15:34
1  
@jzx Indeed, we strive to be like the fabled Hobbits. youtube.com/watch?v=G49RUPv5-NU –  Pharap Aug 21 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

share|improve this answer
    
What does ClampMagnitude do, isn't it the same code as Normalize * Constant in disquise? –  Krom Stern Aug 21 at 13:02
2  
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 at 13:20
1  
+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 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 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 at 19:43

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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