- Home /
Issues with Camera Follow script - large jitter when resetting to initial position
I've got a CameraFollow script for my 2D project and I'm using it to do a pan of the level when it is loaded by setting the initial camera position on the opposite side of the level from the player. The script follows the player quite well and clamps to the bounds as I'd like it too, but during the initial pan there is a large jump in the y direction after it gains focus on the player. I'm very new to Unity and C# so I don't know much about what I'm doing. I took this from the 2D platformer example/tutorial and modified it slightly to fit my needs. I'm hoping someone can take a peak and let me know what I'm doing that might cause the final pan of the camera to jump so much (100px or more). Thanks!!
using UnityEngine;
using System.Collections;
public class CameraFollow : MonoBehaviour
{
public float xMargin = 1f; // Distance in the x axis the player can move before the camera follows.
public float yMargin = 1f; // Distance in the y axis the player can move before the camera follows.
public float xSmooth = 8f; // How smoothly the camera catches up with it's target movement in the x axis.
public float ySmooth = 8f; // How smoothly the camera catches up with it's target movement in the y axis.
private Vector2 maxXAndY; // The maximum x and y coordinates the camera can have.
private Vector2 minXAndY; // The minimum x and y coordinates the camera can have.
private Transform player; // Reference to the player's transform.
private GameObject sky;
public static bool cameraInit;
void Awake ()
{
// Setting up the reference.
player = GameObject.FindGameObjectWithTag("Player").transform;
// Determine the bounds of the camera
Camera cam = Camera.main;
float camHeight = 2.0f * cam.orthographicSize;
float camWidth = camHeight * cam.aspect;
sky = GameObject.FindGameObjectWithTag("sky");
minXAndY.x = sky.renderer.bounds.min.x + 0.5f * camWidth;
maxXAndY.x = sky.renderer.bounds.max.x - 0.5f * camWidth;
minXAndY.y = sky.renderer.bounds.min.y + 0.5f * camHeight;
maxXAndY.y = sky.renderer.bounds.max.y - 0.5f * camHeight;
cameraInit = true;
}
bool CheckXMargin()
{
// Returns true if the distance between the camera and the player in the x axis is greater than the x margin.
return Mathf.Abs(transform.position.x - player.position.x) > xMargin;
}
bool CheckYMargin()
{
// Returns true if the distance between the camera and the player in the y axis is greater than the y margin.
return Mathf.Abs(transform.position.y - player.position.y) > yMargin;
}
void Update ()
{
// By default the target x and y coordinates of the camera are it's current x and y coordinates.
float targetX = player.position.x;
float targetY = player.position.y;
// If the player has moved beyond the x margin...
if(CheckXMargin())
// ... the target x coordinate should be a Lerp between the camera's current x position and the player's current x position.
targetX = Mathf.Lerp(transform.position.x, player.position.x, xSmooth * Time.deltaTime);
// If the player has moved beyond the y margin...
if(CheckYMargin())
// ... the target y coordinate should be a Lerp between the camera's current y position and the player's current y position.
targetY = Mathf.Lerp(transform.position.y, player.position.y, ySmooth * Time.deltaTime);
// The target x and y coordinates should not be larger than the maximum or smaller than the minimum.
targetX = Mathf.Clamp(targetX, minXAndY.x , maxXAndY.x);
targetY = Mathf.Clamp(targetY, minXAndY.y , maxXAndY.y);
// Set the camera's position to the target position with the same z component.
transform.position = new Vector3(targetX, targetY, transform.position.z);
if (cameraInit == true && Mathf.Abs(transform.position.x - minXAndY.x) < 0.01f)
{
cameraInit = false;
}
}
}
Answer by Issah · Aug 04, 2014 at 08:45 AM
Hello,
http://docs.unity3d.com/ScriptReference/MonoBehaviour.LateUpdate.html
" For example a follow camera should always be implemented in LateUpdate because it tracks objects that might have moved inside Update."
When you'r camera follow the transform.position in update, the value can be calculated at the wrong moment, between two frame like you say, try to put you'r following instruction in LateUpdate and your forces in FixedUpdate.
Im not sure it will enought but maybe it will be easier to debug with the correct LateUpdate function.
Thanks for that, originally the Unity tutorial had this in FixedUpdate and it was very jittery. I moved it to LateUpdate and the issue isn't fixed. At the point when this is occurring the player is stationary.
I worked on debugging it a bit more and it seems my main issue is in the CheckY$$anonymous$$argin function. The issue is a logical one and what is happening is that Lerp isn't good for panning the camera back to the original position because I'm Lerp'ing between the camera's position and the player's position which ends up causing very small changes in the targetY coordinate as it approaches the destination. I've replaced the initial camera panning with a standard linear equation using a distance factor: targetY = transform.position.y + (targetY - initialY) * Time.deltaTime / 3.0f;
This works O$$anonymous$$, but now for some reason when I'm resetting the level I get a big jump in the camera position right when it starts moving back. It seems to have to do with using late update because the player is moved, camera jumps to his y position, then pans. I'll figure it out at some point.
Thanks for turning me on to LateUpdate!
Would upvote you, but I don't have the rep yet :(