Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice

Question FPS Controller through Cinemachine - HOW to avoid SHAKING/JITTER?

Discussion in 'Cinemachine' started by hibanlosano, Dec 5, 2022.

  1. hibanlosano

    hibanlosano

    Joined:
    Mar 18, 2020
    Posts:
    4
    Hello there,

    Recently I've started to play with Unity again, and in my FPS project I've been dealing with this for a long while now, just like many others who create dozens of posts in Unity forums about the usual Cinemachine camera jitter when dealing with movement, animating, etc.

    I wish something as straightforward as rotating a Rigidbody with the camera could be done and forgotten under a minute, but it's clearly one of those difficulty curves that turn into a wall for so many, myself included right now.

    So here's my case: I have a RigidBody which I move using AddForce(VelocityChange) to then manually modify its velocity value (only multiply per drag on X and Z) to add resistance and avoid sliding. For the Camera inputs, I have the typical Virtual Camera + Camera inside Pivot inside Character setup, using CinemachineInputProvider. The Body is Lock to Target and Aim is POV, smoothed with acc/dec time. Follow attribute attached to the Pivot of my Camera, which is positioned at head level of my humanoid character.

    I press play, everything is smooth and the animations I set up in Animator aren't causing any trouble. Everything is smooth as it should be. Now, there's one little problem: my character needs to rotate horizontally with the Camera. I can do that no problem by script getting a reference of the Camera rotation, but no matter how or where I do it, rotation is always shaky. Both CinemachineBrain Update and Blend Update methods are in FixedUpdate, as they've shown better results and everything I physically move is in Fixed Update. Rigidbody is in Interpolate as well.

    Now, I don't know exactly when does the Chinemachine Camera rotation happen, and I suspect that could have something to do with this. I've done the intuitive thing: reading its rotation, converting it into a new Vector3 with the axis I need and applying that rotation to the Rigidbody in both FixedUpdate and LateUpdate, using different methods (using lerp, transform.eulerAngles, MoveRotation,etc.) but none seems to solve the issue.

    So, if you need more details of my setup, screenshots or even project files - I can provide no problem. I only wish someone could explain to me what's happening here. Everything around the character is smooth though, only I can't attach any weapon because rotating will make it shake. I know it's not the camera that shakes, but I don't know how to sync both rotations to the eyes of my camera. Feel free to correct me if you think I'm reading this whole thing wrong.

    Thanks in regard guys, have a great day.
     
  2. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,267
    FixedUpdate + Interpolation is suspect. The point of Interpolation is that the physics system will generate render frames by interpolating between the fixed physics frames. This makes the motion compatible with standard Update loop (that's the whole point). So if your camera targets are interpolated RigidBodies, you should put the CM Brain in LateUpdate or SmartUpdate, otherwise you will get jitter because you're misinforming it.

    I don't understand what you mean by "my character needs to rotate horizontally with the Camera". Can you describe the camera behaviour that you want, and how it relates to player motion? Is there a published game that has this behaviour? I could look at a video so I understand what you're trying to do.
     
  3. hibanlosano

    hibanlosano

    Joined:
    Mar 18, 2020
    Posts:
    4
    I understand your first point about interpolation and have made the correspondent changes (with no success sadly), but I should say that it's not exactly that my camera targets a Rigidbody, it's an FPS camera with a full humanoid body where the idea is that you'll be able to see the body when looking down. There's plenty of examples I could give, but my standard reference right now would probably be Tiny Tina Wonderlands (Borderlands movement and feeling in general). In this video you can kind of see how I want the player to move, also being a coop gameplay you can see the player movement behaviour from an outside perspective.


    I should say now I have my camera outside the character, with Follow attribute pointing to a pivot I have inside the character. Look At attribute is empty. My current code gets the rotation from the camera in Update to then call rb.MoveRotation(Quaternion.Euler(desiredRotation)) in FixedUpdate.
     
  4. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,267
    Thanks for the info. Can you show a video of the jitter in your scene? You can DM me if you're uncomfortable posting publicly.
     
  5. hibanlosano

    hibanlosano

    Joined:
    Mar 18, 2020
    Posts:
    4
    Here's the video. I have a couple of quick rigs, not fully implemented, with a weapon. While doing this to make a quick demonstration I encountered that also the hands of my character are flicking. Something secondary that doesn't bother me right now as I downloaded this model and haven't really looked into it beyond having a basic skeleton to move, but maybe worth mentioning.



    I have also tried interpolating on and off the rigidbody with no visible changes.
     
  6. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,267
    I'm pretty sure the problem lies in your strategy of pulling the rotation from the camera and applying it to your gameobject.

    I'm thinking that you should change your approach. Can you try something like this?
    1. Make an invisible GameObject inside your character at eye level to represent the camera
    2. Put the CM vcam as a direct child of that GameObject (or just add the CinemachineVirtualCamera behaviour directly to it)
    3. Set the Aim and Body of the vcam to Do Nothing
    4. Make a script to rotate the GameObject in response to mouse movement
    That way, you are in full control of the camera, and Cinemachine will just ensure that the MainCamera is where it needs to be, at the end of the frame. That's a much cleaner setup, IMO.
     
  7. hibanlosano

    hibanlosano

    Joined:
    Mar 18, 2020
    Posts:
    4
    So I should just give up on the whole CinemachineInputProvider workflow and update my Rigidbody rotation and Camera position/direction directly through a script right? Or updating this pivot object's rotation? Which doesn't make sense to me.
     
  8. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,267
    CinemachineInputProvider is a way of providing input to a CM camera that wants it. Your usecase is more that the user is moving the character's head and the camera is attached to that, so you should build it that way. There are lots of scripts out there to make a pivot rotate in response to mouse input. Why make your life complicated? Feeding back the camera's rotation into an object that's driving the camera's rotation is asking for trouble.