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:
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;
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);
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.
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
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
dampparameter 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.
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.
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!