Player movement relative to the camera

I’m new to unity so I wanted to start by making simple controls for a player. The player is a ball that rolls using physics, so i’m using addForce instead of transform.position.

Whats the best way to control the player with the camera like this?:

W = add force horizontally away from the camera

S = add force horizontally towards the camera

A,D = add force left or right

Space = jump

Then I think I can figure out how to make the camera orbit the player and follow.

I think I need a way to get the direction from the camera to the player(with raycast?)
then to push the player at 0, 0+180, 0+90, or 0-90 degrees of that direction depending on which button is down. I couldn’t find any tutorials on how to do that.

From tutorials and the manual I only found out how to make it move relative to the scene, but that wouldnt really work if the camera can rotate around the player.

Well it’s very similar to do it relative to the camera, the only thing that will change is what value you are applying (I’m assuming that relative to the scene you’ve just been adding things like Vector3.Left, Vector3.Right or the equivelent new Vector3(1.0f, 0.0f, 0.0f) etc)

To move relative to the camera you can simply use some of the helper values of the Transform component that exists as part of every gameObject (even the camera).

So for example right, relative to the main camera, would be.

Camera.mainCamera.transform.right;

You can use the inverse of this for the camera left, the forward value (instead of right) and its negative for away from and towards the camera respectively, and its up and down for your jumping.

Keep in mind however that if your camera is pitched up or down, then the forward vector will not be level with the “floor” of the world.

Hope this helps as a point in the right direction.

One way to approach it is to consider what direction means what; more specifically, is the camera’s right unconditionally “right” and is the ground’s forward unconditionally “forward”?

That said, here’s a general approach I’ve often taken on this:

// C#

// character and camera Transform variables may or may not be necessary
Transform player;
Transform cam;

// This establishes basic controls relative to the camera
Vector3 controlRight = Vector3.Cross(cam.up, cam.forward);
Vector3 controlForward = Vector3.Cross(cam.right, Vector3.up);

// Apply movement to control input
Vector3 controlInput = (controlRight * Input.GetAxis("Horizontal")) + (controlForward * Input.GetAxis("Vertical"));

With some tweaks and personalization, this may serve as a reasonable starting point.

Edit: In case you might be wondering why I bothered with controlRight (since cross(cam.up, cam.forward) is simply cam.right), it’s for the sake of having a point to branch off from. The controls don’t have to exclusively be based on the camera itself, so thinking ahead to separate the controls into two pieces can save a lot of headache later.

Thanks, I almost got it to work like this:

using UnityEngine;
using System.Collections;

public class CameraController : MonoBehaviour {
	
	public GameObject player;
	public GameObject cam;

	public Transform playerT;
	public Transform camT;


	private Vector3 offset = Vector3.zero;

	void Start () {
		offset = camT.position - playerT.position;
	}

	void LateUpdate () {
		camT.LookAt(playerT);//allways look at player

		if ( Input.GetMouseButton( 1 ) ) {//right click is down
			camT.RotateAround(playerT.position, Vector3.up, Input.GetAxis("Mouse X"));//look horizontally
			camT.RotateAround(playerT.position, Vector3.left, Input.GetAxis("Mouse Y"));//look vertically
		}
		camT.position = playerT.position + offset;//keep same distance from player
	}
}

The only problem left is that the offset interferes with the camera rotating. The offset is meant to keep the camera a certain distance away from the player, but now it also controls the exact position relative to the player instead of just the distance. I want to have a zoom distance variable that can be controlled by the mouse wheel.

I think it’s a simple solution that i’ll eventually figure out to somehow update the offset every time the camera is rotated, but does anyone want to give me a hint? :smiley:

Vector3 move = Quaternion.Euler(0, camera.eulerAngles.y,0) * new Vector3(h,0,v).normalized;

Vector3 dir = transform.InverseTransformDirection(move);
float Turn = Mathf.Atan2(dir.x,dir.z);
transform.Rotate(0, Turn * someSpeed,0);