Physics + first person camera = jitter?

I have spent a couple of hours trying to solve a seemingly trivial problem in an efficient way. Preface: I have many years of experience with Unity and am aware of the common pitfalls related to camera animation.

When having a fast moving object driven by physics, having a camera closely follow the object leads to intense jittering.

Everything happens in FixedUpdate and I have tried lerping the camera both in FixedUpdate and LateUpdate. Both interpolation and extrapolation have been tried. Fixing the camera to the object in question (either via parenting or simply setting the position in LateUpdate) eliminates the stuttering but is not acceptable as I want a certain inertia to the camera.

Which leads me to the question.
Is the current physics implementation in Unity inherently jittery in a way that following a rigidbody too closely will reveal frame by frame inconsistencies?
Even though FixedUpdate runs on a fixed timestep (which Update/LateUpdate does not) I had expected the interpolation methods to leave me with a consistent movement.

As it stands I can think of two workarounds:

  1. Have a visual model follow the physics rig. It will be a tiny bit behind but this should not be visible. This way the camera will follow the stable (but “late”) visual model instead. I am confident this would work, but it adds overhead to the programming and rigging.
  2. Fix the camera to the physics object and implement my own stable routines to simulate the inertia.

I would be very thankful for some input on this. In particular from Unity devs or experienced members. Thanks in advance!

This seems to be a long standing “problem” in the Unity community, and it seems to never have been properly answered.

I am relatively certain the improper use of Lerp is the cause. x = Mathf.Lerp(x, targetvalue, Time.deltatime) is simply an sloppy approximation of an exponential function. It will work fine in situations where an exact interpolation is not critical.
But in the case of a first person / chase camera following a quick moving object, it simply will not be exact enough.

There are several ways to properly solve the problem:

  1. Use a physics driven camera as well and use forces/springs to make it behave as intended.
  2. Implement a custom inertia model that uses available data to simulate inertia as needed.
  3. Write a proper exponential function that is accurate for frame rate fluctuations.

I am going with option #2 as it suits our needs the best, and a quick test proves my answer. The jittering is gone and the camera behaviour is as intended.
So in the end this had very little to do with Unity physics, and like I mentioned earlier I suspect this is the case for the majority of similar questions here and on the forums.

So, having just run this gauntlet myself, here is my thought which was alluded to in AlwaysSunny’s Comment.

That basically the physics is running at a different frequency than the game. So here is my somewhat simple solution to the problem.

In your camera code, track the delta time that is actually accumulated on that physics update, and then use that delta time to calculate your camera velocities.

There is probably a more unity friendly way to do this, but in any case here is the list of what i did in my code and it completely removed the jitters.

Note: this only works for following physical objects, for something moved in Update(), you can just use deltaTime in your late update, but then again you probably aren’t getting jitters.

float AccDeltaTime = 0.0f;

void FixedUpdate()
{

 AccDeltaTime += Time.fixedDeltaTime;  // is there a way to query how physics update occurred?

}

void LateUpdate()
{

  Vector3.Lerp( current, target, rate * AccDeltaTime );

  AccDeltaTime = 0.0f;

}

@IkeHerman In your code what would I set rate to?
What value should I use?

I also had a jerky ride for a FPS on a lift. I tried what I could, including making the FPS a child of the lift. What seems to be happening was that the lift wouldn’t move at the same speed as the physics. As the lift fell, the FPS was always catching up with the gravity and for much as I played with gravity speeds or interpolation, it never got acceptably smooth.

I found a reasonable workaround (after many hours).

My lift animation was triggered by the pushing of a button. I included in the code attached to the button a changing of the main camera to a secondary camera which was mounted in the lift (to change cameras: Switch Camera to an Additive Loaded Scene - Unity Answers). This gave a perfectly smooth view.

Then I attached a simple mouse-look-around code to the camera (https://answers.unity.com/questions/29741/mouse-look-script.html- I used the second easier script by Andy P-123), so although it wouldn’t move whilst in transit, you could still look around as if it was still the FPS.

I also deactivated the FPS whilst I was on the secondary camera, otherwise, there could be some discoordination and the FPS might be invisibly moved away.

Since the FPS was deactivated, I had to temporarily make the FPS a child of the lift, otherwise, it wouldn’t fall with gravity until it was reactivated at the end. To make it a child:

FPS.transform.parent = MyLiftObjectName.transform;

I put in a check to make sure that when the animation finishes, the FPS becomes active again, the camera resets to main and to stop the FPS being a child of the lift object.

void Update()
    {
        if (animator.GetCurrentAnimatorStateInfo(0).IsName("AnimationNameInInvertedCommas"))
        {
            FPS.SetActive(true); //public GameObject FPS; was declared at beginning of the script.
            //Disable the second camera
            m_CameraTwo.enabled = false;
            //Enable the Main Camera
            m_MainCamera.enabled = true;
            //reset FPS so it is no longer a child of the lift
            FPS.transform.parent = null;
        }
   }

I ended up using this solution to trigger the end of the journey as a mesh collider trigger didn’t seem to work. I think this was because the FPS was inactive so it didn’t make the trigger.