- Home /
Camera follow jitter
Hello guys, I know this is a common issue, I tried many suggested solutions but none worked for me.
I have a rigidbody (spaceship) moving in a 3D space; since I'm using forces, controls are in FixedUpdate and interpolation is active. The rigidbody is an empty GameObject, and the spaceship elements (engines, body, etc) are simple children of the GameObject. The controls script is oviously attached to the rigidbody (GameObject).
If I use a static camera (child of the spaceship), everything is smooth. If I use a "smooth follow camera", everything looks jittery (even though the "game" runs at stable 60fps with V-Sync on).
This is the camera script I'm using:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CameraFollow : MonoBehaviour
{
public Transform target;
public float distance = 27.0f;
public float height = 2.0f;
public float damping = 0.5f;
public float rotationDamping = 0.5f;
void FixedUpdate()
{
Vector3 desiredPosition = target.TransformPoint(0f, height, -distance);
transform.position = Vector3.Lerp(transform.position, desiredPosition, damping);
Quaternion desiredRotation = Quaternion.LookRotation(target.position - transform.position, target.up);
transform.rotation = Quaternion.Slerp(transform.rotation, desiredRotation, rotationDamping);
transform.LookAt(target, target.up);
}
}
Now I'm wondering: the target of this script is a transform (and it's actually pointing to an element of the ship called "CameraTarget", an empty object, child of the main rigidbody)... Maybe the target should be a rigidbody itself? Or being a child of the rigidbody, basically a part of it, there's no difference?
Thank you in advance.
Answer by Ermiq · Nov 20, 2019 at 03:10 PM
After a long time I've spent trying to get smooth camera with no jittering while using rigidbody driven character I've ended up switching to CharacterController
.
Yes, there are Rigidbody.Interpolation
, different update loops for different things, and so on, but sadly it's never good enough. In some cases it's possible to get satisfying results, but it's never ideal unless you reinvent the wheel from scratch, like implementing custom update loops, custom interpolation methods and other stuff.
However, there's one thing I want to suggest. Maybe it will help you. Your Lerp()
usage is wrong. It's very very common mistake though, and it caused by many not good enough lerp tutorials. The thing is, you use the damp
parameter in Lerp(source, target, damp)
functions in wrong way. It leads to a situations where the more the delay between frames/updates, the faster your camera have to move to reach the target position between updates, and it turns out that smoothing the camera this way makes the camera even more jittery.
The solution is to pre-damp/pre-smooth the damp
parameter itself. Read this thread: https://forum.unity.com/threads/camera-stutters-in-a-simple-rotation.389899/ and what the user roridriscoll
have wrote there. His lerp method works great for smooth camera following, and that's how all Lerp()
methods should be done to be real smoothing methods.
Hello, first of all, thanks for your answer @Ermiq . The camera code I posted is a quite old code found years ago on the Unity wiki page (if I recall correctly). I have read the thread you linked and I need to do some tests and research: it looks quite tricky.
Anyway, for a simpler/temporary solution, I managed to eli$$anonymous$$ate the jitter by placing both the rigidbody and camera scripts in FixedUpdate. I have read everywhere that camera should always go in LateUpdate, but LateUpdate and FixedUpdate occour at different times (once per frame vs once per physics step) so we get the jitter. Placing the camera in FixedUpdate (where it should go, since it's following an object moving in FixedUpdate), the jitter goes away but there's a constant micro-stuttering on the environment (noticeable when rotating or passing close to other objects), like it's going at a lower framerate. The cause is the visual (camera) moving in FixedUpdate, hence updating its position every 0.02 seconds (or 50 times per second). Apart from using Lerp in a different way as you suggested, I think it is an unavoidable issue regarding rigidbodies moving in FixedUpdate: they always tend to stutter (sometimes it's very subtle but a trained eye can spot it): so I decided to lower the fixed timestep to 0.01667 and now everything looks perfectly smooth, because physics (and everything running in FixedUpdate) now update 60 times per second, along with everything else in Update with V-Sync on.
Answer by U2-84 · Nov 20, 2019 at 10:50 AM
A little update. The overall look is now smooth. Controls are still in FixedUpdate, while the camera is now handled in LateUpdate. But... there's a new problem now: if I look closely at my ship, I see it's "shaking" (slightly). The shake effect is more noticeable if I use a very close camera. I tried everything: both controls and camera in update, controls in update and camera in lateupdate, both controls and camera in fixedupdate, etc... They all give me worse results (more shaking and/or environment jitter/micro stuttering); the smoothest combination is controls in fixedupdate (since I'm moving a rigidbody) and camera in lateupdate. But the shaking ship is driving me crazy. Is there a way to have a camera smooth following physics objects without collateral issues? Edit: just before someone points it out, the shake effect isn't related to floating point precision. I'm using a floating origin system so the player ship is always close (<1000m) to the origin.
Answer by WakingDragon · Jan 11, 2021 at 09:10 AM
A common reason for jitter is a script moving a gameobject to an accurate position, and never quite settling on it. So one technique to try is to expose a variable for "accuracy" and only attempt to move the gameobject if it is further from its target than the accuracy variable. In pseudo code...
if(distanceToTargetOrAngleFromTargetAngle > accuracy)
{
//do your position, rotation, etc
}
//else do nothing
There are other causes of jitter of course!