- Home /
Local Third Person Movement based off Camera Rotation
I am attempting to make a 3rd person character controller using a rigidbody. I need the character to move based off local rotation and position, as I am having the player walk on a spherical planet. I already have the planet gravity down, but I’ve encountered a problem with my movement script.
My camera can be rotated freely on the y axis. I want the player to face the same direction the camera is facing when the player moves. I intended to track the rotation of the camera whilst the player isn’t moving, and then add the angle between the camera’s rotation last time the player moved and the current rotation of the camera to the player’s rotation, in an attempt to accurately rotate the player to where the camera is facing, but the resulting rotation is negligible.
Looking back, I believe it would be better to use the rotation of the camera directly to influence the player’s rotation, but I’m not quite sure how to do that.
“Camera X” is mapped to mouse x.
Any help or tips would be appreciated.
I also would like to make the character face the direction they move when moving with wasd, but that’s a whole other endeavor. Regardless, if you have any pointers on how I could do that, they would also be appreciated.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class BestMove : MonoBehaviour
{
// reference Main Camera
public Transform cam;
Vector3 CinCamRot1;
Vector3 CinCamRot2;
// The stored difference in camera rotation since the last movement
float StoredCamRotChange;
// The difference in camera rotation since the last void Update
float TempCamRotChange;
float xInput;
float zInput;
Vector3 moveVector3;
float speed = 4f;
bool strafeToggle = false;
// Start is called before the first frame update
void Start()
{
CinCamRot1 = new Vector3 (0, cam.localRotation.y, 0);
}
// Update is called once per frame
void Update()
{
// CinCamRot2 is the rotation of the camera from THIS void Update.
CinCamRot2 = new Vector3 (0f, cam.localEulerAngles.y, 0f);
// States that TempCamRotChange is the angle between last void Update's camera rotation and this void Update's camera rotation
TempCamRotChange = Vector3.Angle(CinCamRot1, CinCamRot2);
// Sets TempCamRotChange to be negative if the camera rotated left
float CamXinput = Input.GetAxis("Camera X");
if (CamXinput < 0f)
{
TempCamRotChange = -TempCamRotChange;
}
// Updates the StoredCamRotChange float to include this void Update's change in rotation since last void Update
StoredCamRotChange = StoredCamRotChange + TempCamRotChange;
xInput = Input.GetAxis("Horizontal");
zInput = Input.GetAxis("Vertical");
// Used to see if the user is attempting to move.
moveVector3 = new Vector3(xInput, 0f, zInput).normalized;
if (moveVector3.magnitude > 0.1f)
{
Move();
}
// CinCamRot1 is the rotation of the camera from the previous void Update up until this point. (now its the rotation from this update)
//CinCamRot1 = new Vector3 (0f, cam.localEulerAngles.y, 0f);
// Sets the TempCamRotChange float back to zero for the next void Update, as it is used to tell the difference between the last Update's rotation and this Update's
TempCamRotChange = 0f;
}
void Move()
{
//movement
// Different movement for strafing vs free movement
if (strafeToggle == true)
{
// Strafe Movement
// when I end void Move, I reset StoredCamRotChange to zero, so I need to make sure I set the camera's (x probably) rotation to the same as the player's when I press the lock on button
}
else
{
// Free Movement
// Rotate relative to camera
transform.Rotate(0, StoredCamRotChange * Time.deltaTime, 0, Space.Self);
// Move relative to facing direction
transform.Translate(xInput * Time.deltaTime * speed, 0, zInput * Time.deltaTime * speed);
}
StoredCamRotChange = 0f;
// I moved this from update to here, so now it is the camera rotation from last time the player moved.
CinCamRot1 = new Vector3(0f, cam.localEulerAngles.y, 0f);
}
}
You could just put an empty object as a child of the player transform and always have it aligned with the y axis of your player, then make the camera a child of that empty object. When you want to rotate your camera, rotate the empty parent so now the empty parent and the camera are facing the same direction, when you want to point your player in that direction you just rotate to the same direction the empty child (Empty parent and empty child is the same object here, it is a child of player and parent of camera) is facing with a look rotation for example. But keep in $$anonymous$$d that you will have to rotate the child against the rotation of the player by the same amount as the players rotation whenever you want to rotate the player independently of the camera. Also, in a setup I have, I put an empty as a child on the player and an additional empty as a child of the first empty where the camera should be. Then instead of having the camera as a child, it just does a smooth camera follow of the empty that is where it should be. Then I use an additional empty as a look at target for the camera which I set at different heights depending on the situation.