Camera always behind player in Unity3d
Solution 1
You need to move your camera position based on sphere movement direction -
public GameObject player;
private Vector3 offset;
float distance;
Vector3 playerPrevPos, playerMoveDir;
// Use this for initialization
void Start () {
offset = transform.position - player.transform.position;
distance = offset.magnitude;
playerPrevPos = player.transform.position;
}
void LateUpdate () {
playerMoveDir = player.transform.position - playerPrevPos;
playerMoveDir.normalize();
transform.position = player.transform.position - playerMoveDir * distance;
transform.LookAt(player.transform.position);
playerPrevPos = player.transform.position;
}
Edit 2: To fix flickering camera, try this -
void LateUpdate () {
playerMoveDir = player.transform.position - playerPrevPos;
if (playerMoveDir != Vector3.zero)
{
playerMoveDir.normalize();
transform.position = player.transform.position - playerMoveDir * distance;
transform.position.y += 5f; // required height
transform.LookAt(player.transform.position);
playerPrevPos = player.transform.position;
}
}
Solution 2
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CameraFollow : MonoBehaviour {
public GameObject player;
public float cameraDistance = 10.0f;
// Use this for initialization
void Start () {
}
void LateUpdate ()
{
transform.position = player.transform.position - player.transform.forward * cameraDistance;
transform.LookAt (player.transform.position);
transform.position = new Vector3 (transform.position.x, transform.position.y + 5, transform.position.z);
}
}
Solution 3
My solution (based on @brennon-provencher answer) with smoothness and auto offset:
public class CameraFollow : MonoBehaviour
{
public GameObject target;
public float speed = 5;
Vector3 offset;
void Start()
{
offset = target.transform.position - transform.position;
}
void LateUpdate()
{
// Look
var newRotation = Quaternion.LookRotation(target.transform.position - transform.position);
transform.rotation = Quaternion.Slerp(transform.rotation, newRotation, speed * Time.deltaTime);
// Move
Vector3 newPosition = target.transform.position - target.transform.forward * offset.z - target.transform.up * offset.y;
transform.position = Vector3.Slerp(transform.position, newPosition, Time.deltaTime * speed);
}
}
HB1963
Updated on June 04, 2022Comments
-
HB1963 almost 2 years
I'm struggling with this for quit some time now. I have GameObject, being a sphere, which is my player on a 3d Terrain. I have a Camera which is always on a fixed distance from the player, follows it where it goes with below script:
public GameObject player; private Vector3 offset; // Use this for initialization void Start () { offset = transform.position - player.transform.position; } void LateUpdate () { transform.position = player.transform.position + offset; }
So far so good. However what I actually want is that the camera rotates with the player, so it always looks into the direction where the sphere is moving, but always stays behind the player at the same fixed distance, so that the player is always visible in the camera view.
There are a lot of scripts available, but the problem with the onces I've seen so far is that the camera indeed rotate with the player, but because the player actually is a rolling sphere the camera view is rolling and turning as well.
The best script I found so far is below, but this one has the same problem as the other onces, the camera rolls with the player.
public Transform target; public float distance = 3.0f; public float height = 3.0f; public float damping = 5.0f; public bool smoothRotation = true; public bool followBehind = true; public float rotationDamping = 10.0f; void Update () { Vector3 wantedPosition; if(followBehind) wantedPosition = target.TransformPoint(0, height, -distance); else wantedPosition = target.TransformPoint(0, height, distance); transform.position = Vector3.Lerp (transform.position, wantedPosition, Time.deltaTime * damping); if (smoothRotation) { Quaternion wantedRotation = Quaternion.LookRotation(target.position - transform.position, target.up); //Quaternion ownRotation = Quaternion.RotateTowards; transform.rotation = Quaternion.Slerp (transform.rotation, wantedRotation, Time.deltaTime * rotationDamping); } else transform.LookAt (target, target.up); }
Can anyone help me with this please?
-
HB1963 almost 7 yearsThx Mukesh. Nearly there. The camera follows the player and always stays behind. Unfortunately for some reason the camera view is flickering now. Any idea?
-
Mukesh Saini almost 7 yearsIs camera always flickering or only when sphere is not moving?
-
HB1963 almost 7 yearsHi Mukesh, camera is always flickering. It looks like as if it is showing a view from two differerent zoom levels.
-
Mukesh Saini almost 7 yearsTry checking if the player movement is recorded as
Vector3.zero
because in that case camera position will be same as player position. I've updated the Edit section in answer for this. -
HB1963 almost 7 yearsHi Mukesh, been away for a while. This did it. Thx very much. One last question. The camera is now on player level, how can I make it looking "over the shoulder" of the player, so floating above and behind the player?
-
Mukesh Saini almost 7 yearsI've updated the answer to give it some height. You can make the height configurable in unity inspector or store the initial camera height in start function and then use that.
-
HB1963 almost 7 yearsI'm afraid that doesn't work. Building end in error: "Cannot modify the return value of 'UnityEngine.Transform.positon' because it is not a variable"
-
Mukesh Saini almost 7 yearsIn
UnityEngine.Transform.positon
you are missing ani
aftert
in the spelling of transform'sposition
variable. -
HB1963 almost 7 yearsSolved it. float yy = transform.position.y; yy += 5f; transform.position = new Vector3 (transform.position.x, yy, transform.position.z);
-
Someone Somewhere about 4 yearsthis is great if you want the camera to follow. In my case, I always want the camera to look at an object from the objects' right side"
Vector3 newPosition = target.transform.position - target.transform.right * offset.x - target.transform.up * offset.y;
-
Shn over 3 yearsThis is working as of 8/6/2020. Short and sweet answer!