Smooth First-Person Camera on a Rigidbody [How to]

This thread is more of an instruction on this matter rather than me asking for an answer, so anyone looking to make a character that uses a Rigidbody which uses forces to move and to slap a camera on their heads, then here’s how to do it right!

I’ve been making a 3D third-person platformer that also has a first person view (FPV) mode. The character has a Rigidbody and uses forces and velocity to move. The movements are done in FixedUpdate() and naturally you would use the ‘interpolate’ interpolation mode in the Editor for the Rigidbody to give the character a smooth movement when jumping and what not. This is a must, otherwise I can guarantee you that you will have stuttering motion in the characters movement.

And then we have Mr Camera. All of the movements are done in LateUpdate(), so that it can work around the characters physics-based movements. This is just camera-following-a-rigidbody-101.

But lets implement that FPV mode. Slap the camera on the characters head and… stuttering? But, it works so well when the camera moves independently from the character. The issue here is that now that the camera is moving one-to-one with a physics based object, it’s just not going to keep up because the way that the camera displays the image on the screen can’t be done in the same way that the physics update internally. If you’ve ever played Far Cry 3, you will know what I’m talking about; if you strafe to the right and move the camera left, whatever’s in front of you will appear to shake uncontrollably. This also happens with Unity’s ‘RigidbodyFPSController’ asset; go on, test it out and move around a cube or something… you’ll see the problem.

So, what is the answer here? Do we lerp the camera independently to the character to simulate being stuck on the characters head? Well that would give us a smooth, independent camera movement but… wait, now we see the character stuttering. Why is this happening?!

Okay, so here’s how you do it. Take everything you learned at the start regarding the 101 joke and throw it in the bin. What we’re going to do is, when the character goes into FPV mode, set the interpolation to ‘None’. That’s right, no more interpolated movement. And all the code to move the camera up/down/left/right in the camera’s script? Shove that all into FixedUpdate(). And what do we have? Flawlessly smooth movement. Strafe around objects and watch them smoothly sail by. It’s beautiful.

So I hope you’ve all learned something here today, and that you all make good use of this information!

4 Likes

Thanks for the info! Interpolation and rigidbodies expose odd behavior sometimes. I’ve come to a situation today where I had a kind of chain made up of rigidbodies attached by joints. One of them exhibited visible stuttering. Disabling and re-enabling interpolation in runtime solved the issue in this case.

@JanDawid

I just want to say that I love you for posting this and asserting so strongly that it works. I’ve literally been wrestling with this problem for what seems like the better part of a century (ok, maybe just a month or so) and this is pretty much the only thing that I never tried because it seemed so ridiculous–after having taken so many suggestions that later proved to not work, I was a bit skeptical. I can indeed confirm that this solution removed the very distracting camera jitter–I should also note that this still worked properly even in a third-person RPG (even with Interpolate/LateUpdate etc. enabled, I was having some major issues)

Thanks again for posting this!

1 Like

My pleasure. I’m really shocked that this jarring oddity is still present in the FPSRigidbody standard asset, and that not many people notice it. It took me forever to find this combination so I’m glad that it reached some people.

Also do note, that if you may notice some stuttering in the editor, it’ll most likely be gone in the build. The editor has a tendency to create jitters where there really aren’t any.

For some reason when I try this it works in fixing the jittering, but my camera looking seems to be at a lowered framerate. Here is my camera code:
float lookHor = Input.GetAxis(“Mouse X”);
float lookVert = Input.GetAxis(“Mouse Y”);

transform.Rotate(0, lookHor * lSpeed, 0);
cam.transform.Rotate(-lookVert * lSpeed, 0, 0);

There is another way: leave the interpolation on and move the camera in OnPreCull.

Some how this works thank you so much

Isnt still the problem here, that now you have lost the smooth,actual frame accurate mouse movement and look?

1 Like

For me I separated the camera from the player and set the player rigidbody to interpolate and then when I do my camera rotations I lerp it by 20.

        mouseX = Input.GetAxisRaw("Mouse X") * sensitivity;
        mouseY = Input.GetAxisRaw("Mouse Y") * sensitivity;

        xSmoother = Mathf.Lerp(xSmoother, mouseX, smoothness * Time.deltaTime);
        ySmoother = Mathf.Lerp(ySmoother, mouseY, smoothness * Time.deltaTime);

        yRotation += xSmoother;
        xRotation -= ySmoother;
        xRotation = Mathf.Clamp(xRotation, -90f, 60f);

It looks like butter in editor and build!