Move Player relative to Camera

I’ve been trying to figure this out for a while but I can’t seem to get my player to move relative to the camera. When I press W and S I move up and down in world space and left and right in world space when I press A and D. How can I make it so that W moves me forward in the direction the camera is looking, A and D left and right of where the camera is looking and S moving towards the camera.

Here’s the player movement script:

using UnityEngine;
using System.Collections;

public class Player : MonoBehaviour
{
    public float moveSpeed;
    public float rotationSpeed;
    Vector3 previousLocation;
    Vector3 moveDirection;

    void Update ()
    {
        moveDirection = Vector3.zero;
        previousLocation = transform.position;
        if (Input.GetKey (KeyCode.W)) moveDirection.z = 1;
        if (Input.GetKey (KeyCode.S)) moveDirection.z = -1;
        if (Input.GetKey (KeyCode.A)) moveDirection.x = -1;
        if (Input.GetKey (KeyCode.D)) moveDirection.x = 1;

        transform.position = Vector3.Lerp(transform.position, transform.position +
        moveDirection.normalized, Time.fixedDeltaTime * moveSpeed);

        if (moveDirection != Vector3.zero)
        transform.rotation = Quaternion.Lerp(
        transform.rotation, Quaternion.LookRotation(transform.position - previousLocation),
        Time.fixedDeltaTime * rotationSpeed);
     }
}
1 Like

So if you want to move relative to the direction of the camera (or any object), then we first need to know the rotation of that object. So let’s add a reference in your script:

public Transform relativeTransform;

Next, instead of using absolute values, when setting your move direction, let’s use the direction the camera is facing:

        if(Input.GetKey(KeyCode.W)) moveDirection += relativeTransform.forward;
        if(Input.GetKey(KeyCode.S)) moveDirection += -relativeTransform.forward;
        if(Input.GetKey(KeyCode.A)) moveDirection += -relativeTransform.right;
        if(Input.GetKey(KeyCode.D)) moveDirection += relativeTransform.right;

Now, based off your code so far, it seems that you only want the player to move on a plane (only x and z directions), so we will want to remove any y movement that the camera’s rotation may have included.

        moveDirection.y = 0f;

Here is the entire script, modified with a few extra changes. Basically, I just cleaned up and simplified the code so that the speed values aren’t arbitrary. Now moveSpeed is in units/second, and rotationSpeed is in degrees/second.

using UnityEngine;
using System.Collections;

public class TempPlayer : MonoBehaviour
{
    public float moveSpeed;
    public float rotationSpeed;

    public Transform relativeTransform;

    void Update()
    {
        Vector3 moveDirection = Vector3.zero;
        if(Input.GetKey(KeyCode.W)) moveDirection += relativeTransform.forward;
        if(Input.GetKey(KeyCode.S)) moveDirection += -relativeTransform.forward;
        if(Input.GetKey(KeyCode.A)) moveDirection += -relativeTransform.right;
        if(Input.GetKey(KeyCode.D)) moveDirection += relativeTransform.right;

        moveDirection.y = 0f;

        transform.position += moveDirection.normalized * moveSpeed * Time.deltaTime;

        if(moveDirection != Vector3.zero)
            transform.rotation = Quaternion.RotateTowards(transform.rotation, Quaternion.LookRotation(moveDirection), rotationSpeed * Time.deltaTime);
    }
}

Just make sure to assign your camera to relativeTransform in the inspector. Hope this helps!

5 Likes

Thank you! I really appreciate you going through it step by step, it really becomes clear that way. Also, thank you for cleaning up the code too.

I signed up just to thank you my friend. You are awesome!

5 years later, this script and fix have helped me so much. Thank you!!!

1 Like