- Home /
Camera does not rotate with player movement
Dear community,
I am experimenting on how to achieve a follow camera with rotation in unity3d. I am trying to mimic a camera setup just like mario64. Player can move and jump but the camera is a pain. The camera does not rotate with the player, it kinda snap on all axis and i am stuck. Can someone please take a look.
This is the player script:
using UnityEngine;
using System.Collections;
public class Player : MonoBehaviour
{
public float horizontalSpeed = 1.0f;
public float verticalSpeed = 1.0f;
public float rotationSpeed = 60.0f;
public float jumpSpeed = 8.0f;
public float gravity = 14.0f;
private Vector3 moveDirection = Vector3.zero;
private CharacterController controller;
void Update()
{
controller = gameObject.GetComponent<CharacterController>();
if (controller.isGrounded)
{
float horizontalDirection = Input.GetAxis("Horizontal") * horizontalSpeed;
float forwardDirection = Input.GetAxis("Vertical") * verticalSpeed;
moveDirection = new Vector3(horizontalDirection, 0, forwardDirection);
if (Input.GetButton("Jump"))
{
moveDirection.y = jumpSpeed;
}
}
else
{
float horizontalDirection = Input.GetAxis("Horizontal") * horizontalSpeed / 2;
float forwardDirection = Input.GetAxis("Vertical") * verticalSpeed / 2;
moveDirection = new Vector3(horizontalDirection, moveDirection.y, forwardDirection);
moveDirection.y -= gravity * Time.deltaTime;
}
if (moveDirection.magnitude > 0.05)
{
transform.LookAt(transform.position + new Vector3(moveDirection.x, 0, moveDirection.z));
}
controller.Move(moveDirection * Time.deltaTime);
}
}
and this is the camera script:
using UnityEngine;
using System.Collections;
public class FollowCamera : MonoBehaviour
{
public GameObject target;
public float damping = 1;
Vector3 offset;
void Start ()
{
offset = target.transform.position - transform.position;
}
void LateUpdate ()
{
float currentAngle = transform.eulerAngles.y;
float desiredAngle = target.transform.eulerAngles.y;
float angle = Mathf.LerpAngle(currentAngle, desiredAngle, Time.deltaTime * damping);
Quaternion Rotation = Quaternion.Euler(0, desiredAngle, 0);
transform.position = target.transform.position - (Rotation * offset);
transform.LookAt(target.transform);
}
}
Answer by dscroggi · Oct 22, 2012 at 06:40 AM
Maybe something like this?
transform.rotation = Quaternion.Slerp(transform.rotation, target.rotation, damping);
transform.position = transform.rotation * Vector3.back * offset + target.position + Vector3.up;
Answer by Skynet2012 · Oct 22, 2012 at 07:47 AM
Thanks for you answer Daniel but the solution didn't work for me. i got a error at target.rotation and transform.rotation Vector3.back offset.
Where do i have to put the code exactly?
Thanks in advance
Answer by dscroggi · Oct 22, 2012 at 11:16 AM
Well in general there should be two things happening.
First the camera should have a home, and when it is not there, slowly move to it.
The second thing is to set the home of the camera based on the player's input.
The code I used is for a mouse so I'm guessing keyboard input will need to be modified slightly.
Looking over the code it looks like I mistook the "target" variable as a transform. Since it is a GameObject we will need to also reference the transform component:
transform.rotation = Quaternion.Slerp(transform.rotation, target.transform.rotation, damping);
I don't know how your scripts are hooked up in the scene, but either way it is always a good idea to cache transform variables. Actually the less dots in variable names, the better. So what we should do is declare a private Transform variable and in the Start or Awake methods is say variable = Camera.main.transform or GameObject.FindGameObjectsWithTag("MainCamera") or just drop the prefab on it manually.
Anyway, the line of code above should smoothly rotate the camera to face the same direction as the player, all that's left is to set the position of the camera back and up from the player's position, which is what the second line of code does. Also ideally the distance (offset) variable could be hard coded like 10 or whatever distance you want. That way if the camera position gets goofed, the camera will follow the distance not the other way around.
Also one last thing, generally the camera will only want to follow the Y rotation of the player, unless you're doing some tomb raider style game where the camera moves all over. In this case you'd want to say something like this
cached_camera.rotation = Quaternion.Euler(0, cached_player.localEulerAngles.y, 0);
That should set the camera's Y to match up with the player's Y, and actually it would be best to plug that into the second argument of the Quaternion.Slerp call so that it's smooth. Rotates from current Y rotation to player's Y.
using UnityEngine;
public class CameraControls : MonoBehaviour
{
private static Transform cached_camera;
private static Transform cached_player;
private static float distance = 10;
void Start()
{
cached_player = GameObject.FindGameObjectWithTag("Player");
cached_camera = transform;
}
void LateUpdate()
{
cached_camera.rotation = Quaternion.Slerp(cached_camera.rotation, cached_player.rotation, 0.05f);
cached_camera.position = cached_camera.rotation * Vector3.back * distance + cached_player.position + Vector3.up;
}
}
Hope that helps.