Search Unity

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

Discussion in 'Physics' started by JanDawid, Apr 26, 2016.

Thread Status:
Not open for further replies.
  1. JanDawid

    JanDawid

    Joined:
    Jul 7, 2014
    Posts:
    283
    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!
     
  2. Edy

    Edy

    Joined:
    Jun 3, 2010
    Posts:
    2,508
    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.
     
  3. Multithreaded_Games

    Multithreaded_Games

    Joined:
    Jul 6, 2015
    Posts:
    122
    @Jakeiiii

    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!
     
    JanDawid likes this.
  4. JanDawid

    JanDawid

    Joined:
    Jul 7, 2014
    Posts:
    283
    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.
     
  5. Darkmatter520

    Darkmatter520

    Joined:
    May 12, 2014
    Posts:
    12
    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);
     
  6. AxPetre

    AxPetre

    Joined:
    Jun 1, 2013
    Posts:
    96
    There is another way: leave the interpolation on and move the camera in OnPreCull.
     
  7. ZuckerburgGaming

    ZuckerburgGaming

    Joined:
    Jul 10, 2019
    Posts:
    10
    Some how this works thank you so much
     
  8. topitsky

    topitsky

    Joined:
    Jan 12, 2016
    Posts:
    100
    Isnt still the problem here, that now you have lost the smooth,actual frame accurate mouse movement and look?
     
  9. Yeowza

    Yeowza

    Joined:
    May 9, 2014
    Posts:
    48
    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.

    Code (CSharp):
    1.         mouseX = Input.GetAxisRaw("Mouse X") * sensitivity;
    2.         mouseY = Input.GetAxisRaw("Mouse Y") * sensitivity;
    3.  
    4.         xSmoother = Mathf.Lerp(xSmoother, mouseX, smoothness * Time.deltaTime);
    5.         ySmoother = Mathf.Lerp(ySmoother, mouseY, smoothness * Time.deltaTime);
    6.  
    7.         yRotation += xSmoother;
    8.         xRotation -= ySmoother;
    9.         xRotation = Mathf.Clamp(xRotation, -90f, 60f);
    It looks like butter in editor and build!
     
Thread Status:
Not open for further replies.