Menu
CoddyTech

Move Where You Look

Part of the Building Real Games section of Coddy's Unity journey. Lesson 42 of 60.

When the camera looks at the player from an angle, the arrows should move the player as the screen shows it: up walks away from the camera, right walks to the camera's right. The world's axes only do that while the camera looks along +z. So build the move from the camera's own directions, cam.forward and cam.right.

They need cleaning first. A camera that looks down at the player has a forward that points into the ground, so set its y to 0 to keep only the part along the ground. What is left is shorter than 1, about 0.87 for a camera tilted down 30 degrees, and the player would walk slower, so normalize it. This walker follows the main camera, which looks down at a corner of the level:

Transform cam = Camera.main.transform;

Vector3 forward = cam.forward;
forward.y = 0f;
forward.Normalize();
Vector3 right = cam.right;
right.y = 0f;
right.Normalize();

Vector3 move = forward * Input.GetAxisRaw("Vertical") + right * Input.GetAxisRaw("Horizontal");
if (move.magnitude > 1f) move.Normalize();   // diagonals no faster
controller.Move(move * speed * Time.deltaTime);

Camera.main is the camera tagged MainCamera. The two directions are read every frame, so the controls stay right when the camera turns. Up and right together add two unit vectors at right angles, which is about 1.41 long, so the move is normalized when it is longer than 1.

challenge icon

Challenge

Medium

Make the arrows walk the player relative to the turning camera.

  1. In Update(), copy cam.forward and cam.right, with y 0, normalized.
  2. dir is forward times the raw "Vertical" axis plus right times "Horizontal", normalized when longer than 1.
  3. When dir != Vector3.zero, set transform.rotation = Quaternion.LookRotation(dir);. Build move from dir * speed.

Press Play: up walks away from the camera, whichever way it looks. Then Check.

Try it yourself

using UnityEngine;

public class Mover : MonoBehaviour
{
    public float speed = 4f;
    public float gravity = -15f;
    public Transform cam;

    CharacterController controller;
    float verticalSpeed;

    void Start()
    {
        controller = GetComponent<CharacterController>();
    }

    void Update()
    {
        if (controller.isGrounded && verticalSpeed < 0f)
        {
            verticalSpeed = -2f;
        }
        verticalSpeed += gravity * Time.deltaTime;

        // Walks along the world's axes: make it walk relative to cam, and face the way it walks
        Vector3 move = new Vector3(Input.GetAxisRaw("Horizontal"), 0f, Input.GetAxisRaw("Vertical")) * speed;
        move.y = verticalSpeed;
        controller.Move(move * Time.deltaTime);
    }
}

All lessons in Building Real Games

Practice on your own: Unity playground