How I can make camera rotate smoothly followed object?
I have a game where is camera top to down and it is driving game. Now I need that camera follow car smoothly not just parenting. This is my code that works with the position. Problem is when the car turns 45 degrees or 90 degrees and then the screen is not turning. So I need to know how I can make the camera rotate smoothly same direction than the car. But camera should rotate only in the x-axis. The y-axis is always 90 degrees and the z-axis is 0 degrees.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SmoothFollow : MonoBehaviour {
public float interpVelocity;
public float minDistance;
public float followDistance;
public GameObject target;
public Vector3 offset;
Vector3 targetPos;
// Use this for initialization
void Start()
{
targetPos = transform.position;
}
// Update is called once per frame
void FixedUpdate()
{
if (target)
{
Vector3 posNoZ = transform.position;
posNoZ.z = target.transform.position.z;
Vector3 targetDirectionZ = (target.transform.position - posNoZ);
interpVelocity = targetDirectionZ.magnitude * 5f;
targetPos = transform.position + (targetDirectionZ.normalized * interpVelocity * Time.deltaTime);
transform.position = Vector3.Lerp(transform.position, targetPos + offset, 0.25f);
Vector3 posNoX = transform.position;
posNoX.x = target.transform.position.x;
Vector3 targetDirectionX = (target.transform.position - posNoX);
interpVelocity = targetDirectionX.magnitude * 5f;
targetPos = transform.position + (targetDirectionX.normalized * interpVelocity * Time.deltaTime);
transform.position = Vector3.Lerp(transform.position, targetPos + offset, 0.25f);
}
}
}
You mentioned the camera is top down. That would mean you are rotating it around the y axis. In Unity terms y is the vertical axis. If you are planning to use physics as well, you might be better of adjusting to Unity, or I can help you adjusting my code. In the answer I will need to keep it correct for the default Unity world space in case others are looking for the same answer.
Answer by frankslater · Sep 23, 2017 at 11:06 AM
I see others posted as well by the time I setup the environment and wrote the code, but give this a try:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SmoothFollow : MonoBehaviour {
public Transform target;
public float followSpeed = 3f;
public float rotationSpeed = 3f;
float distance;
Vector3 position;
Vector3 newPos;
Quaternion rotation;
Quaternion newRot;
// Use this for initialization
void Start() {
distance = transform.position.y - target.position.y;
position = new Vector3(target.position.x, target.position.y + distance, target.position.z);
rotation = Quaternion.Euler(new Vector3(90, target.rotation.eulerAngles.y, 0f));
}
void FixedUpdate() {
if (target) {
newPos = target.position;
newPos.y += distance;
newRot = Quaternion.Euler(new Vector3(90f, target.rotation.eulerAngles.y, 0f));
position = Vector3.Lerp(position, newPos, followSpeed * Time.deltaTime);
rotation = Quaternion.Lerp(rotation, newRot, rotationSpeed * Time.deltaTime);
transform.position = position;
transform.rotation = rotation;
}
}
}
The up and down direction might not be the same axis for you. In that case just change the axis, or let me know what your up direction is and I'll change it for you.
The position and rotation variables are to save on the performance, so you are not accessing transform.position and transform.rotation that many times.
UPDATE: Thanks @Tap1 for accepting the answer. Let me know how you get on with shakiness. I did write a quick and dirty target mover script I tested it with on the morning (moved a cube object around) and it seemed smooth to me. Here is that code if it helps:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CarMover : MonoBehaviour {
public float speed = 30f;
public float rotationSpeed = 60f;
Vector3 rotationEuler;
float turn;
void Start() {
rotationEuler = transform.rotation.eulerAngles;
}
void FixedUpdate() {
float inputHorizontal = Input.GetAxis("Horizontal");
float inputVertical = Input.GetAxis("Vertical");
rotationEuler.y += inputHorizontal * rotationSpeed * Time.deltaTime;
transform.rotation = Quaternion.Euler(rotationEuler);
transform.localPosition += transform.forward * inputVertical * speed * Time.deltaTime;
}
}
Also made a video video about running it in Unity.
Wait this is now shaky. How I can smoothly move camera with mathf.lerp in this code. Can you make smoother code?
By shaky, do you mean jerky? If so, do both your camera and target are updated in FixedUpdate()?
Could better help if I could see the issue. I built a quick test environment before I posted the code but that could be very different from what you are trying to do. Do you $$anonymous$$d sending me the code that updates your target?
It's been a while since I've done this and I didn't use Time.deltaTime to the calculations (which is recommended to be used "because it automatically returns the right delta time if you are inside a FixedUpdate"). Updated the scripts in the answer. That wouldn't cause shakiness on its own thought. What is your Fixed timestep value (Edit > Project Settings > Time)?
Answer by Creeper_Math · Sep 22, 2017 at 09:03 PM
Could try adding in this after your movement script
Vector3 targetRotation = target.transform.rotation.eulerAngles;
Vector3 cameraRotation = transform.rotation.eulerAngles;
transform.rotation.Euler(Vector3.Lerp(cameraRotation,targetRotation));
I added this to my code but it underlines it and print error "$$anonymous$$ember ' Quaternion.Euler (Vector3)' cannot be accessed with an instance reference qualify it with a type name ins$$anonymous$$d" What this mean? And also Lerp need 3 parameters but I added Time.deltaTime and I think that work.