Player moves too quickly diagonally/ doesn't move with camera

I have an FPS, diagonal movement is faster than non-diagonal movement.

``````public class CharControl : MonoBehaviour {

public float speed = 10.0F;
public Camera camera;

// Use this for initialization
void Start ()
{

}

// Update is called once per frame
void Update () {

float translation = Input.GetAxis("Vertical") * speed;
float straffe = Input.GetAxis("Horizontal") * speed;
translation *= Time.deltaTime;
straffe *= Time.deltaTime;

transform.Translate(straffe, 0, translation);
``````

I’ve managed to fix the increase in diagonal speed by using another script, however in this script the player doesn’t move in accordance with the camera (pressing up always moves cardinal north, regardless of which way the camera is facing, for example)

``````public class CharControl : MonoBehaviour {

public float speed = 10.0F;
public Camera camera;

// Use this for initialization
void Start ()
{

}

// Update is called once per frame
void Update () {

float translation = Input.GetAxis("Vertical") * speed;
float straffe = Input.GetAxis("Horizontal") * speed;
Vector3 move = new Vector3(straffe, 0, translation);

transform.position += Vector3.ClampMagnitude(move, speed) * Time.deltaTime;
``````

How do I make it so that the player’s diagonal speed isn’t faster while still moving in accordance with the camera?

Hey! I feel ya. I had that problem a few months ago.

For this there are two good methods but in either case you will just want to limit the diagonal movement.

Option 1: Use a limiter to check to see if both vertical and horizontal are being applied and apply a multiplier of .7071 (that is a bit of a magic constant which is rounded but it comes out of the trigonometry involved in this problem).

Something like this (UNTESTED):

``````void Update () {

float translation = Input.GetAxis("Vertical");
float straffe = Input.GetAxis("Horizontal") * Time.deltaTime * speed;

if (translation != 0f && straffe != 0f) {
translation *= .7071;
straffe *= .7071;
}

translation *=  Time.deltaTime * speed;
straffe *= Time.deltaTime * speed;

Transform.Translate(straffe, 0, translation);
}
``````

Option 2: Add them to a vector and normalize the vector. This brings the magnitude of the entire vector down to a max of 1.

``````void Update() {
Vector3 direction = new Vector3(0f, 0f, 0f);
direction.x = Input.GetAxis("Horizontal");
direction.y = Input.GetAxis("Vertical");

direction.Normalize();

direction *= speed * Time.deltaTime;
transform.Translate(direction);
}
``````

I’d vote for option 2. In either case I’m sure you can tighten up my code a bit but that should get you started. Keep the faith!

So imagine the movement.
Your script is viewing the input as a square.
Instead view it as a circle.
To do that go back to the Pythagoras theorem.
Using your code the length of the movement vector with two sides of length 1 is the square root of 2
However when you are moving along only the x axis then the length of the vector is 1.
To fix this I did:

``````Update()
{
rawInput.x = Input.GetAxis("Horizontal");
rawInput.y = Input.GetAxis("Vertical");
if (rawInput.magnitude >= 1)
{
movement.x = (rawInput.x / rawInput.magnitude);
movement.y = (rawInput.y / rawInput.magnitude);
}
else if(rawInput.magnitude > 0)
{
movement.x = rawInput.x;
movement.y = rawInput.y;
}
else
{
movement.x = movement.x / logarithmicDragCoef;
movement.y = movement.y / logarithmicDragCoef;
}
}
``````

Normalizing the vector is what : `movement.x = (rawInput.x / rawInput.magnitude);`
is achieving

The else if: `else if(rawInput.magnitude > 0)`

Makes it so that any less than 1 input isn’t just set to a 1
(looking back I think I need to normalize this too)

The else runs: `movement.x = movement.x / logarithmicDragCoef;`

So that once input is stopped it slows down using whatever coefficient feels good