Why is keyboard faster than gamepad?

When I use the gamepad/joystick, the character moves correctly, at expected velocity.
When I use the keyboard, it’s ok only when I press one key at a time, but…

Once I press the keys down + left, or up + right, for example, the character moves much faster than normal.

float moveHorizontal = Input.GetAxis("Horizontal");
float moveVertical = Input.GetAxis("Vertical");
Vector3 movement = new Vector3(moveHorizontal, 0, moveVertical);
rigidbody.AddForce (movement * speed * Time.deltaTime, ForceMode.VelocityChange);

Any clues as to what could be causing this unwanted speed?

Again, the gamepad works perfectly for some reason, only the keyboard causes this error. I imagine someone may have encountered this also as it is based on the Roll-A-Ball tutorial project. Thank you for any ideas on this.

I’m not sure but it could be a matter of vector magnitude. Gamepad always gives you the same vaue when max tilted, no matter the direction, while two perpendicular vectors added gives you a vector with a higher magnitude than its two components. If you normalize the vector you get from the keyboard input, you’ll get same value for any direction.

In case this helps anyone else:

movement = Vector3.ClampMagnitude(movement, 1.0f)

Setting it this way seems to have better results than normalising so far (keeps sensitivity of joystick).

When adding forces, you are using the vectors magnitude in the physics calculations. With 3-dimensional vectors, magnitude is calculated with:

M = sqrt( x*x + y*y + z*z);

This means if you hold “up” on the gamepad or press “W” on the keyboard, you get Vector3(0, 0, 1), and a magnitude of sqrt(1 + 0 + 0) or 1. If you hold two directions however, such as down and right, you get Vector3(-1, 0, 1) and a magnitude of sqrt(1 + 0 + 1) or about 1.41. This is what gets used in the force update, and this is where the extra speed is coming from.

As for why you only get the error with your keyboard, it may have something to do with the physical build of your gamepad, or how it calculates the numeric values for the corners. Normally, this would be an issue with the keyboard and the gamepade, but your gamepad might not return full upper values (1.0F) for both X and Y when in a corner.

Plus, you don’t just want to normalize the vector, because normalizing creates a “unit vector”, a vector with any direction, but a magnitude of only 1. As you just want to limit the magnitude to 1, Vector3.ClampMagnitude() is indeed the correct choice here.