Getting rid of double movement speed?

Hi, I currently have a ball that rolls around when you press one of the WASD keys

But when I press two simultaneously, it gives the speed from both keys to that direction

Such as (W give 10 speed forward, D gives 10 speed right, but WD gives 20 speed top-right)

Is there a way I can fix this? Please explain your idea if you can too, trying to learn here =D Let me know if there is any additional info you need, Thanks again!

Here is the script I have for movement so far

var Speed = 0;

function Move()
{
		if (Input.GetKey (KeyCode.W))
			{
				rigidbody.AddTorque(Vector3.right * Speed);
				rigidbody.AddForce(0, 0, Speed);	
			}
			
		if (Input.GetKey (KeyCode.S))
			{
				rigidbody.AddForce(0, 0, -Speed);
				rigidbody.AddTorque(Vector3.left * Speed);
			}
			
		if (Input.GetKey (KeyCode.A))
			{
				rigidbody.AddForce(-Speed, 0, 0);
				rigidbody.AddTorque(Vector3.forward * Speed);
			}
		
		if (Input.GetKey (KeyCode.D))
			{
				rigidbody.AddForce(Speed, 0, 0);
				rigidbody.AddTorque(Vector3.back * Speed);
			}
	
}

function FixedUpdate()
{
		if (Input.GetKey (KeyCode.W))
		{
			Move();
		}
		
		if (Input.GetKey (KeyCode.S))
		{
			Move();	
		}
		
		if (Input.GetKey (KeyCode.A))
		{
			Move();
		}
		if (Input.GetKey (KeyCode.D))
		{
			Move();
		}
	
		if (Input.GetKey(KeyCode.Space))
		{
			if (letJump)
			{
				Jump();
			}	
		}
		
}

This is an old, “classic” problem dating back to the beginning of the FPS days. A lot of competitive FPS players use this “trick” in affected games to gain a speed boost. I think it is called “crossing the square”, but google is really failing me right now on the subject.

To manage input, instead of checking for key pressed, it is probably better to use Input.GetAxis(). This will return a value of from -1 to 1 in each movement direction, and on the plus side will automatically work with gamepads and joysticks.

So the updated code would go something like this:

Vector3 direction = new Vector3(0,0,0);
direction.x = Input.GetAxis("Horizontal");
direction.z = Input.GetAxis("Vertical");
direction.Normalize();
rigidbody.AddForce( direction * Speed );

The above should be the entire contents of the Move() function, aside from any extras that you may put in there. The line “direction.Normalize()” will take the vector that is already pointing in the correct direction and make it only 1 unit long. Thus, you will be able to multiply by “Speed” to get the correct amount.

A better answer is to use ClampMagnitude. Normalizing your movement vector will always restrict it to a magnitude of 1 (or zero if the vector’s magnitude is too small). ClampMagnitude on the other hand will leave your magnitude alone unless it exceeds a your maxLength value.
Since you’re multiplying by speed, you will want to clamp to the maxLength of 1.

Vector normalization, for one.

Basically you want to multiply the speed by (roughly) 0.7071 if you’re going to be moving on an angle. It has something to do with the length of the vector making the distance traveled ridiculous.

What I would do is organize the code better so that instead of directly calling move after each individual input, you could do something like if ( W && D) Speed * 0.7071, which is the other reason why it’s not working.

If you hit 2 buttons with your current code, the function is called twice.

Basically, record all of the input you receive. Then at the end of the function, use another Move() method to actually call the direction. If it’s a diagonal, multiply the speed by .7071 (I believe Vector3.normalize does the same thing).