Input.GetAxis doesn't seem to move me in the direction I am facing

I am trying to make a first-person-controlled, zero-gravity environment where you pretty much move in the direction you are facing, current velocity willing. (I’m using rigidbody movement) The scripts I am about to display work almost exactly how I want, except that the forward movement when looking up or down from the world X-Z plane doesn’t move to where I am looking. For example, if I hit the start button and don’t move the mouse to keep looking forward and hold W, I will move exactly forward. But if I move my mouse upward and and looking more vertically, when I hold W down, I move at less of an upward angle than where I am looking. How can I fix that?

For mouse look I am using this script:

// Performs a mouse look.

var horizontalSpeed : float = 2.0;
var verticalSpeed : float = 2.0;

function FixedUpdate () {
    // Get the mouse delta. This is not in the range -1...1
    var h : float = horizontalSpeed * Input.GetAxis ("Mouse X");
    var v : float = verticalSpeed * Input.GetAxis ("Mouse Y");
    transform.Rotate (-v, h, 0);
}

For the character controller I am using this script:

// These variables are for adjusting in the inspector how the object behaves 
var maxSpeed = 7.000;
var force = 8.000;
var jumpSpeed = 5.000;

// These variables are there for use by the script and don't need to be edited
private var state = 0;
private var grounded = false;
private var jumpLimit = 0;

// Don't let the Physics Engine rotate this physics object so it doesn't fall over when running
function Awake ()
{ 
    rigidbody.freezeRotation = true;
}

// This part detects whether or not the object is grounded and stores it in a variable
function OnCollisionEnter ()
{
    state ++;
    if(state > 0)
    {
        grounded = true;
    }
}


function OnCollisionExit ()
{
state --;
    if(state < 1)
    {
        grounded = false;
        state = 0;
    }
}

// This is called every physics frame
function FixedUpdate ()
{


    // Get the input and set variables for it
    jump = Input.GetButtonDown ("Jump");
    horizontal = Input.GetAxis("Horizontal"); 
    vertical = Input.GetAxis("Vertical"); 

    // Set the movement input to be the force to apply to the player every frame
    horizontal *= force;
    vertical *= force;

    // If the object is grounded and isn't moving at the max speed or higher apply force to move it
    if(rigidbody.velocity.magnitude < maxSpeed)
    {
        rigidbody.AddForce (transform.rotation * Vector3.forward * vertical);
        rigidbody.AddForce (transform.rotation * Vector3.right * horizontal);
    }

    // This part is for jumping. I only let jump force be applied every 10 physics frames so
    // the player can't somehow get a huge velocity due to multiple jumps in a very short time
    if(jumpLimit < 10) jumpLimit ++;

    if(jump && grounded == true && jumpLimit >= 10)
    {
        rigidbody.velocity.y += jumpSpeed;
        jumpLimit = 0;
    }
 }

Here’s your problem:


if(rigidbody.velocity.magnitude < maxSpeed7)
    {
        rigidbody.AddForce (transform.rotation * Vector3.forward * vertical);
        rigidbody.AddForce (transform.rotation * Vector3.right * horizontal);
    }</pre></code>
   

----------

Instead of using Vector3.forward, use

----------

<pre><code>var localForward : Vector3 = transform.TransformDirection(Vector3.forward);

rigidbody.AddForce(localForward * vertical);

Vector3.forward returns (1, 0, 0). Always. So if you are feeding that into a function, forward is always along the X (red) axis, no matter what the rotation is.

TransformDirection() takes a vector and returns the local space version of it. For example, passing in Vector3.forward (1, 0, 0) to a transform that is looking straight up will return (0, 1, 0).

Here’s the documentation on the subject:

http://unity3d.com/support/documentation/ScriptReference/Transform.TransformDirection.html

https://www.3dbuzz.com/training/view/3rd-person-character-system/simple-character-system

Video #7 has a solid explanation of what you need. The whole course can also be useful