- Home /
Help make camera zoom smoother
Hi!
So I've been trying for a while now to make my camera script zoom smoother since right now it can be very jumpy due to the nature of the script and I'd love some help to try and fix that.
using UnityEngine;
using System.Collections;
public class cameraScript : MonoBehaviour {
Transform Player1;
Transform Player2;
public float maxSize = 10;
public float minSize = 5;
public float xMax;
public float xMin;
public float yMax;
public float cameraZoomModifier = 1.8f;
public float xOffset;
public float playerDist;
Vector3 cameraCenter;
PositionChecker posCheck;
void Start(){
posCheck = this.GetComponent<PositionChecker> ();
playerDist = Vector2.Distance(Player1.transform.position, Player2.transform.position);
}
void Update () {
Player1 = posCheck.GetPos (1);
Player2 = posCheck.GetPos (posCheck.GetLength());
playerDist = Vector2.Distance(Player1.transform.position, Player2.transform.position);
cameraCenter = Vector3.Lerp (Player1.transform.position, Player2.transform.position, 0f);
this.transform.position = new Vector3(Mathf.Clamp(cameraCenter.x, xMin, xMax) + xOffset, Mathf.Clamp(cameraCenter.y, -yMax, yMax), -10);
this.GetComponent<Camera>().orthographicSize = playerDist/cameraZoomModifier;
this.GetComponent<Camera>().orthographicSize = Mathf.Clamp(this.GetComponent<Camera>().orthographicSize, minSize, maxSize);
}
}
The game "support" 4 players, Player1 being the one in the lead of the race and Player2 being the one in the far back.
using UnityEngine;
using System.Collections;
public class PositionChecker : MonoBehaviour {
//Names of the player objects
public string[] objectNames;
Transform[] players;
int dnf = 0;
// Use this for initialization
void Start () {
players = new Transform[objectNames.Length];
for (int i = 0; i < objectNames.Length; i++) {
players [i] = GameObject.Find (objectNames [i]).transform;
}
}
// Update is called once per frame
void Update () {
for (int i = 0; i < players.Length; i++) {
if (i == 0) {
} else if (players [i].position.x > players [i - 1].position.x){
Transform j = players[i];
Transform k = players[i - 1];
players [i - 1] = j;
players [i] = k;
}
}
}
//Currently used in the rubber banding to give more stamina to the last players
public float GetLead(Transform obj){
float lead = players[0].position.x - obj.position.x;
/*if (lead < 1)
lead = 1;
Mathf.Clamp (lead, 1, 10);*/
return Mathf.Abs(lead) / 2;
}
//Get the Transform of a player (1 - Max Length)
public Transform GetPos(int pos){
return players [pos - 1];
}
//Get Lenght of players[]
public int GetLength(){
return players.Length - dnf;
}
//Add one to DNF (Did Not Finish)
public void DNF(){
dnf += 1;
}
public int GetDNF(){
return dnf;
}
}
Now, in my player controller script I have a function that checks if that player is out of bounds and then kick him/her from the race and calling DNF() in the position checker script.
Here comes the problem, whenever one player gets kicked out the camera makes a jump since the new player that is in the back is further ahead than the player that got kicked. I'd like this transition to become smoother and not just jump forward.
If someone could help me out it would be very appreciated!
You can use Lerping smoothly increase values, like $$anonymous$$ath.Lerp or Vector3.Lerp. Check the Scritping API for more information.
Answer by Xitech_ · May 02, 2016 at 12:06 PM
Use a Lerp for smooth movements
EDIT: If you do not understand Lerp correctly, watch the official video from Unity
EDIT2: Added a Unitypackage with example how to move a camera via Lerp. Download here
EDIT3: as @Beatrate stated you should put the camera movement in the LateUpdate(), which I did NOT do in the example.
Post your script then and explain what doesn't work and then we can try to help.
Try and read my post again... The scripts are posted and problem explained, if anything is confusing then ask and Ill explain.
Ok, so now Im almost even more confused...
I tried with both Vector3.Lerp and $$anonymous$$athf.Lerp to try and get a good result but nothing. In an attempt to try and understand it better I created a new float called posThingy just to try and wrote this:
posThing = $$anonymous$$athf.Lerp (0, 10, Time.deltaTime);
In my $$anonymous$$d this were suppose to make posThing go from 0 to 10 in a few seconds but it just stuck between 0.15 and 0.20 and jumped back and forth.
I am so confused.
Try
posThing = $$anonymous$$athf.Lerp (posThing, 10, Time.deltaTime);
Are you calling this Lerp function continuously every frame, like in Update() or in a Coroutine?
Well that's simply because of how Lerp works. Lerp stands for linear interpolation. $$anonymous$$eaning if you put in $$anonymous$$athf.Lerp(from,to,factor) it will calculate:
from + ( factor * (to-from));
https://en.wikipedia.org/wiki/Linear_interpolation
so in your example: $$anonymous$$athf.Lerp(0,10,Time.deltaTime) Time.deltaTime is the time between two frames so about 0.01666666666 seconds 0 + Time.deltaTime *(10-0) = 0+ Time.deltaTime*10 = 0.166666666
So when you use methods like that reading up helps ;)
What you can do is the following:
[SerializeField] float smoothTime = 1.0f;
private float timeLeft = 0;
....
void StartSmoothing(){ timeLeft = smoothTime;}
...
void Update(){
...
posThing = $$anonymous$$athf.Lerp(targetPos,posThing,timeLeft);
timeLeft+=Time.deltaTime;
...
}
Answer by Beatrate · May 02, 2016 at 02:10 PM
Move the camera in LateUpdate().
LateUpdate is called after all Update functions have been called. This is useful to order script execution. For example a follow camera should always be implemented in LateUpdate because it tracks objects that might have moved inside Update.
Answer by Ellis · May 02, 2016 at 02:02 PM
To Clear it up.
I added a function in my camera script that allows it to find a "dnf" player and it's position.
I then changed my PlayerDist code to this:
if (Player3 != null) {
posThing = Vector3.Lerp (posThing, Player2.position, Time.deltaTime);
playerDist = Vector2.Distance(Player1.transform.position, posThing);
}
else
playerDist = Vector2.Distance(Player1.transform.position, Player2.transform.position);
Updated Script
using UnityEngine;
using System.Collections;
public class PositionChecker : MonoBehaviour {
public string[] objectNames;
Transform[] players;
int dnf = 0;
// Use this for initialization
void Start () {
players = new Transform[objectNames.Length];
for (int i = 0; i < objectNames.Length; i++) {
players [i] = GameObject.Find (objectNames [i]).transform;
}
}
// Update is called once per frame
void LateUpdate () {
for (int i = 0; i < players.Length; i++) {
if (i == 0) {
} else if (players [i].position.x > players [i - 1].position.x){
Transform j = players[i];
Transform k = players[i - 1];
players [i - 1] = j;
players [i] = k;
}
}
}
//Currently used in the rubber banding to give more stamina to the last players
public float GetLead(Transform obj){
float lead = players[0].position.x - obj.position.x;
return Mathf.Abs(lead) / 2;
}
//Get the Transform of a player (1 - Max Length)
public Transform GetPos(int pos){
return players [pos - 1];
}
//Get Lenght of players[]
public int GetLength(int i){
return players.Length - dnf + i;
}
//Add one to DNF (Did Not Finish)
public void DNF(){
dnf += 1;
GetComponent<cameraScript> ().AddDNF ();
}
public int GetDNF(){
return dnf;
}
}
Your answer
Follow this Question
Related Questions
Make a camera to Follow two players 2 Answers
Smooth camera on moving platform 1 Answer
How to make a camera Follow an Object moving in zigzag path? 1 Answer
camera follow gameobject moving in angular path. 0 Answers
Making camera follow upwards 3 Answers