Search Unity

Camera Jitter, depending on the settings either the player or the environment jitters

Discussion in 'Cinemachine' started by SirWhiteBeard, Feb 4, 2020.

  1. SirWhiteBeard

    SirWhiteBeard

    Joined:
    Feb 21, 2014
    Posts:
    66
    Hi there,

    I have reworked my player controller to be rigibody based and eversince I am experiencing jitter on either the player or the environment. This is especially noticeable when playing in build. I have made a menu to be able to toggle v-sync on and off and when running my build with v-sync off I have approximately 350fps. With the current settings you will notice there will be quite some background jitter. I have tried changing the damping settings, which fixes the background jitter mostly, but causes the player to jitter. I have also changed the update method to FixedUpdate, but this makes the jitter visable with both v-sync turned on and off. I'm running out of options and have no clue where to tackle this problem. I hope someone can help me out!

    For convenience I have added my PlayerController Script and screenshots of the settings on my CinemachineBrain, CinemachineFreeLook and Cinemachine Collider. I'm using Unity 2019.3.0f6 and updated to the most recent version of Cinemachine.

     

    Attached Files:

  2. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,726
    Ususally "either the player or the background jitters" is a symptom of uneven animation. Your character is not moving smoothly, and if that's the case then it's impossible to have a camera show both a smooth background and a smooth player at the same time.

    The solution is to fix your player animation. If it's a rigidBody, make sure all animation is happening in FixedUpdate, never in Update. Maybe try moving the logic in your script from Update() to FixedUpdate().
     
    Last edited: Jul 6, 2021
    lukasc2000, wHo_69 and DerKancso like this.
  3. SirWhiteBeard

    SirWhiteBeard

    Joined:
    Feb 21, 2014
    Posts:
    66
    Hi I understand the problem I think. The movement and it's animations however are already done in FixedUpdate. It's only the jumping that is done via Update as far as I can tell. And is everything is done in FixedUpdate does the CinemachineBrain need to be set to Fixed Update aswel?
     
  4. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,726
    If everything is done in FixedUpdate, then CM Brain should be set to that also. If you set it to SmartUpdate, it will auto-detect how the target moves and report its findings in the vcam inspector when the game is playing. It's helpful for debugging.

    upload_2020-2-4_15-24-15.png
     
  5. SirWhiteBeard

    SirWhiteBeard

    Joined:
    Feb 21, 2014
    Posts:
    66
    Thanks for the headsup regarding the debugging. It is indeed saying FixedUpdate. I have now set the CinemachineBrain Update method to FixedUpdate. Unfortunately I still have the jittering occuring, now even with v-sync turned on. I have tried playing all code of my PlayerController within fixed update, which causes some minor bugs (Jump input unresponsive, which is expected) but the camera still jitters. I will try to make a recording for a more visual representation of the problem.
     
  6. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,726
    With everything on FixedUpdate, does the jitter happen in the build? Does it happen in the Editor when the inspector is not visible?
     
  7. SirWhiteBeard

    SirWhiteBeard

    Joined:
    Feb 21, 2014
    Posts:
    66
    With everything in FixedUpdate it happens in both the Editor with only gameview visible and in build on with both v-sync on and off. I have tried creating a video of the issue, but it's hardly noticeable because of compression. None the less here is a link:


    Edit: it is especially noticeable at the yellow ship and it's light aswel as the trafficsign on the ground when the player/camera gets closer.
     
  8. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,726
    You're right - I can't really see it in the video.

    Maybe it has something to do with the aliasing between physics framerate and render framerate. Have you tried adding Interpolation to your player RigidBody? It's designed to smooth such jitter.

    If you do, then you'll need to put the brain in Smart or Late update. Fixed will jitter, as Interpolate will modify the player's transform in Update.
     
  9. SirWhiteBeard

    SirWhiteBeard

    Joined:
    Feb 21, 2014
    Posts:
    66
    I had already tried that unfortunately without any luck. It's one of the solutions I came across when first googling that issue. I'd happily share a build or the project if you want.
     
  10. SirWhiteBeard

    SirWhiteBeard

    Joined:
    Feb 21, 2014
    Posts:
    66
    Small little update, the problem seems to occur in older builds to 2018.3 and something else I noticed, is that the problem seems to become worse over time and won't be there initially.
     
  11. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,726
    Can you use 2018.4? That's our LTS version and we don't really support any of the other 2018 variations
     
  12. SirWhiteBeard

    SirWhiteBeard

    Joined:
    Feb 21, 2014
    Posts:
    66
    I could download 2018.4 and give it a check, but the issue was present in both 2018.3 and 2019.3,
     
  13. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,726
    oh, I understood from this that the problem was only in builds older than 2018.3
     
  14. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,726
    Do you get the accumulating jitter if you remove Cinemachine and parent the Camera directly to the player?
     
  15. SirWhiteBeard

    SirWhiteBeard

    Joined:
    Feb 21, 2014
    Posts:
    66
    I will give it a shot, if the problem persists than I should see the same background jitter right?
     
  16. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,726
  17. SirWhiteBeard

    SirWhiteBeard

    Joined:
    Feb 21, 2014
    Posts:
    66
    I have disabled the CinemachineManager and parented a new Camera tagged MainCamera with the Post Processing Stack V2 to my player and while I don't have the option to freely look around there is no jitter even after playing for about 5 minutes. With Cinemachine it would start jittering more and more after about 1 minute.

     
  18. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,726
    If you could share a minimal project that reproduces this effect and send it to me I could take a look
     
  19. SirWhiteBeard

    SirWhiteBeard

    Joined:
    Feb 21, 2014
    Posts:
    66
    I'm currently at work, will do so when I get home. Do you have any preference on how or where I upload it? Thank you very much for the support thusfar!
     
  20. SirWhiteBeard

    SirWhiteBeard

    Joined:
    Feb 21, 2014
    Posts:
    66
    I have cleaned up the project a bit. There's only one scene in the scenes folder. You can press "o" for an options menu where you can set the brightness to your liking. If you have an xbox one or ps4 controller it will also work.

    Edit: removed link.
     
    Last edited: Feb 19, 2020
  21. SirWhiteBeard

    SirWhiteBeard

    Joined:
    Feb 21, 2014
    Posts:
    66
    Hi @Gregoryl
    After doing some more experiments with a more barebones project I still get the stuttering unfortunately. This project might be more suitable to take a look at.
     

    Attached Files:

  22. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,726
    Thanks for the upload. I ran the scene and moved the character around but am unable to see any jitter. Is there anything specific I should be looking for, or any specific action I need to do?

    One thing I noticed: you had Interposlation on in the player, but the Brain Update was set to fixed. For now, leave the Brain on Smart Update. As you turn Interpolation on and off on the player, the Brain will figure out the appropriate update mode for the vcam (which for Interpolate is Late, otherwise Fixed).
     
  23. SirWhiteBeard

    SirWhiteBeard

    Joined:
    Feb 21, 2014
    Posts:
    66
    The interpolation should be turned off, but I might have forgotten to turn it off again after experimenting with the project. Which project did you test if I may ask, or did you test both? To see the jitter occuring the fps needs to be high 200+ (v-sync needs to be turned off) and move form left to right or right to left, like in the image. You'll see the blocked stairs jittering from left to right. In the larger project, which I uploaded to google drive it's the same case (when v-sync is turned off and you achieve 200/300 fps) make sure to build the project and walk away as far as possible from the rock with the ship on it, try changing the camera angle and eventually the jittering will start happening. It's really hard to record the jittering since recording will also impact the fps, but I'll give it another shot.



    Edit: I finally managed to record the jitter
     
    Last edited: Feb 7, 2020
  24. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,726
    Camera judder will certainly be caused by uneven movement of the character. To ensure even movement, I did 2 things in your RigidBodyChcarcter.cs: moved all the code to FixedUpdate, and added _inputs.Normalize(). That way, you're for sure moving the character at a fixed speed.

    Then, I see no judder at all, with or without interpolation, and with or without Cinemachine, running at >400 fps.
     
  25. SirWhiteBeard

    SirWhiteBeard

    Joined:
    Feb 21, 2014
    Posts:
    66
    I will give that a shot, would you mind sharing the code you changed exactly? I'm not sure what you mean by _input.Normalize(). And doesn't moving the input to the FixedUpdate cause it to be unresponsive, since it's not checking if there is input every frame?
     
  26. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,726
    Code (CSharp):
    1.     void FixedUpdate()
    2.     {
    3.         _isGrounded = Physics.CheckSphere(_groundChecker.position, GroundDistance, Ground, QueryTriggerInteraction.Ignore);
    4.  
    5.         _inputs = Vector3.zero;
    6.         _inputs.x = Input.GetAxis("Horizontal");
    7.         _inputs.z = Input.GetAxis("Vertical");
    8.         _inputs.Normalize();
    9.         if (_inputs != Vector3.zero)
    10.             transform.forward = _inputs;
    11.  
    12.         _body.MovePosition(_body.position + _inputs * Speed * Time.fixedDeltaTime);
    13.     }
     
  27. SirWhiteBeard

    SirWhiteBeard

    Joined:
    Feb 21, 2014
    Posts:
    66
    Hi @Gregoryl did you have a chance to look at this project? Unfortunately I'm still not having any luck with fixen the jitter in mij project. I have changed various settings and thusfar the only thing to fix it is lowering the fixedtimestep to 0.01, which shouldn't be necessary. I was also wondering what the setting does form the image below, since it is minimizing the jitter although it's still present.



    On a side note, here is some code of how I'm currently handling my movement, but still without any luck.

    Code (CSharp):
    1. void FixedUpdate()
    2.     {
    3.         // Input
    4.         if (GroundCheck() && !rotationBlock)
    5.         {
    6.             inputDir = input.normalized;
    7.             RunAxis();
    8.         }
    9.         else
    10.         {
    11.             inputDir = new Vector3(0, 0, 0);
    12.         }
    13.  
    14.         if (pushControllerScr._pushBlocker)
    15.         {
    16.             input = Vector3.zero;
    17.         }
    18.         else
    19.         {
    20.             input = new Vector3(InputManager.MainHorizontal(), 0, InputManager.MainVertical());
    21.         }
    22.  
    23.         // Makes the player able to move, while not landing or being dead
    24.         if (!landState && !climbManagerScr.isClimbing)
    25.         {
    26.             Move(inputDir, running);
    27.         }
    28.     }
     
  28. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,726
    What does Move() do?
     
  29. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,726
    Can you prove that your character is moving smoothly? Maybe output its velocity each frame and dump it to a spreadsheet and graph it? If the movement isn't smooth then no amount of camera tinkering will fix your problem.
     
  30. SirWhiteBeard

    SirWhiteBeard

    Joined:
    Feb 21, 2014
    Posts:
    66
    This is what move does:
    Code (CSharp):
    1. if (inputDir != Vector3.zero)
    2.         {
    3.             float targetRotation = Mathf.Atan2(inputDir.x, inputDir.z) * Mathf.Rad2Deg + cameraT.eulerAngles.y;
    4.             transform.eulerAngles = Vector3.up * Mathf.SmoothDampAngle(transform.eulerAngles.y, targetRotation, ref turnSmoothVelocity, GetModifiedSmoothTime(turnSmoothTime));
    5.         }
    6.  
    7.         float targetSpeed = ((running) ? runSpeed : movementSpeed) * inputDir.magnitude;
    8.  
    9.         stateInfoBaseLayer = _anim.GetCurrentAnimatorStateInfo(0);
    10.  
    11.         if (stateInfoBaseLayer.IsTag("Climbing") || stateInfoBaseLayer.IsTag("Standing"))
    12.         {
    13.             currentSpeed = 0f;
    14.         }
    15.         else
    16.         {
    17.             currentSpeed = Mathf.SmoothDamp(currentSpeed, targetSpeed, ref speedSmoothVelocity, GetModifiedSmoothTime(speedSmoothTime));
    18.         }
    19.  
    20.         if (stateInfoBaseLayer.IsTag("AirIdle") && currentSpeed > walkSpeed)
    21.         {
    22.             currentSpeed = walkSpeed;
    23.         }
    24.  
    25.         velocity = transform.forward * currentSpeed + Vector3.up * _rb.velocity.y;
    26.  
    27.         if (_capsuleCol.enabled)
    28.         {
    29.             _rb.MovePosition(_rb.position + velocity * Time.deltaTime);
    30.         }
     
  31. SirWhiteBeard

    SirWhiteBeard

    Joined:
    Feb 21, 2014
    Posts:
    66
    I'm unsure how I would be able to do that? Do you mean debug logging the velocity every frame and putting them into a spreadsheet? the stange thing is that the jittering at 300 fps+ is coming and going when walking around. If you walk far away from the yellow ship you can clearly see it jittering from left to right for like 10 seconds and when stopping and walking and changing direction it can go away aswel. Then after a while the jittering comes back. This can only be noticed in build, since in editor I won't achieve 300 fps. I would really appreciate it if you could take a look at the bigger project since I can't seem to recreate the exact scenario in a new project.
     
  32. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,726
    Code looks ok to me. If you can prove a smooth velocity then we can lay this question to rest and look again at the cameras.

    I looked only at the last simplest project you posted, not at the intermediate one. I might be able to check out that one a little later.

    The Blend Update Method controls when the active vcam's settings are blended with the outgoing vcam's settings, and applied to the main camera. I'm surprised it makes any difference to the jitter, since no vcam blends are involved.

    Yes, log to a spreadsheed and graph. Try to do it only when you see the jitter. Note that it might also be rotational jitter. Are you sure that it's not just because of pixel aliasing in the render of distant objects?
     
  33. SirWhiteBeard

    SirWhiteBeard

    Joined:
    Feb 21, 2014
    Posts:
    66
    I understand.

    If you could check out the intermediate one that would be amazing, since it's quite difficult to describe the problems without being able to capture them.

    That's what I was thinking, initially I wasn't even planning to experiment with this setting because of that reason.

    In all honesty I have no clue on how to log the Debug.logs to a spreadsheet or graph. Do I have to do this manually? The jitter also only happens in a standalone build, since this is the only way to achieve 300+ fps on my pc. I'm quite sure it's not pixel aliasing since the jumps from left to right are quite big. Tommorow I will give recording it another try, this has to be filmed by my phone however, because when I'm using recording software the fps in my game drop to a point where the jitter isn't nearly as bad.
     
    Last edited: Feb 10, 2020
  34. SirWhiteBeard

    SirWhiteBeard

    Joined:
    Feb 21, 2014
    Posts:
    66
    @Gregoryl I have been able to get an output_log.txt, which shows the velocity of my RigidbodyController script. Is there a way to convert this to a spreadsheet/graph? There is quite some irrelevant stuff between every frame in the output_log.txt.
     
  35. SirWhiteBeard

    SirWhiteBeard

    Joined:
    Feb 21, 2014
    Posts:
    66
    Hi @Gregoryl just got back from work and I finally managed to get a descent capture of the jittering. Note that this is not all the time, it comes and goes while playing (i.e. rotating the player and walking in other directions might stop it, and it will eventually come back). I also managed to get a dump of the game while playing and made it as readable as possible. It shows the rb.velocity, which only changes on the y when the player jumps (Addforce is used) and the custom velocity which is used to translate the input to the movement (rb.MovePosition). The dump looks clean to me without any jumps between frames.

     

    Attached Files:

    Last edited: Feb 11, 2020
  36. SirWhiteBeard

    SirWhiteBeard

    Joined:
    Feb 21, 2014
    Posts:
    66
    Small little update on the project, someone gave me the tip to create my own custom camerafollow script to check if the jitter/stutter is still present. This custom camerafollow script didn't come with any jitter, so it probably has something to do with Cinemachine. The script I'm using is as follows;

    Code (CSharp):
    1. void FixedUpdate() {
    2.     yaw += InputManager.SecHorizontal() * mouseSensitivity;
    3.     pitch -= InputManager.SecVertical() * mouseSensitivity;
    4.     pitch = Mathf.Clamp(pitch, pitchMinMax.x, pitchMinMax.y);
    5.  
    6.     currentRotation = Vector3.SmoothDamp(currentRotation, new Vector3(pitch, yaw), ref rotationSmoothVelocity, rotationSmoothTime);
    7.     transform.eulerAngles = currentRotation;
    8.  
    9.     transform.position = target.position - transform.forward * dstFromTarget;
    10. }
    So this solved the jitter, but I would really like to use Cinemachine and Timeline in my project, which unfortunately still has the jitter/stutter problem. For this reason I figured I should delete Cinemachine from my project and re-install it (I have been working on this project for about 2 years) and check if that solves it. Unfortunately it didn't, but this made sure I had to rebuild the Freelook camera, the Cinemachine Collider and Cinemachine Brain within my project, so I had a look at all the settings again and did some testing. I eventully found out that the x, y, z damping on the top, middle and bottom rigs caused the major jitter/stutter so that's currently on 0 instead of the standard 1. Like I said this fixes the major horizontal jitter you encouter every now and again while playing, but there is still some jitter which doesn't happen when using my own custom camerafollow script. This seems to be rotational jitter/stutter, but the stutter seems to be there all the time and unfortunately I haven't found a fix yet.
    I have changed my PlayerController script a little bit as you can see below;

    This is my new rotation code:
    Code (CSharp):
    1. float targetRotation = Mathf.Atan2(inputDir.x, inputDir.z) * Mathf.Rad2Deg + cameraT.eulerAngles.y;
    2. targetRotation = Mathf.SmoothDampAngle(transform.eulerAngles.y, targetRotation, ref turnSmoothVelocity, GetModifiedSmoothTime(turnSmoothTime));
    3.  
    4. Quaternion targetRot = Quaternion.AngleAxis(targetRotation, Vector3.up);
    5.  
    6. _rb.MoveRotation(targetRot);
    This is my movement code:
    Code (CSharp):
    1. velocity = transform.forward * currentSpeed + Vector3.up * _rb.velocity.y;
    2.  
    3. if (_capsuleCol.enabled) {
    4.     _rb.MovePosition(_rb.position + velocity * Time.fixedDeltaTime);
    5. }
    Note that this runs in FixedUpdate, which it should.

    Like I said this al leads me to believe the jitter/stutter is caused by Cinemachine, since my movement seems clean/smooth and the jitter/stutter doesn't occur with my custom camera follow script. Below are the settings I currently have on the Rigidbody, Camera and Cinemachine Freelook:









     
    Last edited: Feb 15, 2020
  37. SirWhiteBeard

    SirWhiteBeard

    Joined:
    Feb 21, 2014
    Posts:
    66
    Another small little update, the main cause of the "big jitter" that occasionally happens with v-sync off (300+ fps) is the x, y, z damping on the top, middle and bottom rigs. Turning the standard "1" damping down to 0 "fixes" this.



    Now I'm still encountering constant jitter with the settings mentioned in my previous comment, so I thought going back through the "fixes/suggestions" I had already tried since the situation is a bit different now that I know the damping was causing the major jitter/stutter.
    Eventually I came back to the Cinemachine Brain, Blend Update Method, which is set LateUpdate by default. I first want to demonstrate the custom Camera Follow script I had created for testing, which you can see below:


    Custom Camera Follow script used (No Cinemachine)

    And below are two recordings of the same segment with the Cinemachine Brains Blend Update Method set to LateUpdate (default) and FixedUpdate.


    Note that there is severe jitter while running around the yellow cube. The Blend Update Method is at it's default LateUpdate.


    Here the Cinemachine Brain is set to FixedUpdate the same as the Update Method and all of my movement is also handled in FixedUpdate. And the jitter seems to be gone as far as I can tell.

    Now the question is, like I said in one of the earlier comments I thought I wasn't using any blending, since I'm using only one camere (my main camera). Why does this fix it? And I couldn't find much documention regarding the Blend Update Method, since it seems to be added recently? If someone from Unity could elaborate that would be amazing! What is this Blend Update Method used for?

    Another thing I encounter is alot of misinformation regarding putting your CameraMovement in either Update, FixedUpdate or LateUpdate. The Cinemachine Brain only has 3 options, FixedUpdate, LateUpdate and Smart Update and I think SmartUpdate checks what kind of movement there is and decides whether to use Fixed or LateUpdate. As of now, all my settings are set to FixedUpdate, which also handles my Rigidbody movement (MovePosition and MoveRotation), but I have also been told to strictly use LateUpdate for any camera movement. I hope someone could answer this for me aswel.
     
    Emanx140 and gaborkb like this.
  38. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,726
    Hey @SirWhiteBeard, sorry for the delayed response. I'd like to try to answer some of your questions.

    The first thing to understand is that in Unity there are 2 clocks: the physics clock (fixedUpdate) which runs the physics simulation at a constant rate, and the render clock (update/lateUpdate) which runs at a variable rate which can depend on many things, including whatever other stuff your computer is doing at the moment.

    In your scenario, everything is moving on the physics clock. In a perfect world, you'd move your cameras and render on physics frame boundaries as well, and everything would be jitter-free.

    The problem comes when the render frames don't fall on the same frame boundaries as the physics frames. When that happens you're not presenting a smoothly changing world (because of frame aliasing), and if the camera is targeting something that isn't moving smoothly it will present as jitter.

    To make matters worse, there's no way for Unity to know in advance how long the frame will take to compute, so at best the deltaTime it passes to the simulation for that frame is a guess, based on the previous frame time. There's bound to be some inaccuracy, and if the deltaTime plays a role in the camera position calculation (as it does if damping is enabled) then you could see some jitter, which goes away if you eliminate deltaTime from the equation (e.g. by turning off damping).

    Not necessarily a good idea. Your camera settings depend on what is going on in your scene. Here is a guide for minimizing camera jitter:

    All things move in Update or LateUpdate:
    • Follow on the render clock: Use LateUpdate for both Brain settings
    All things move in FixedUpdate, no interpolation:
    • Follow on the physics clock: Use FixedUpdate for both Brain settings
    Some things move in FixedUpdate, with interpolation, and other things move in Update or LateUpdate:
    • Follow on the render clock: Use LateUpdate for both Brain settings (why? because interpolation modifies the transform of the RigidBody for rendering, based on deltaTime, to combat the aliasing problem. It's as if the thing was moved on the render clock, making it compatible with other things that move on the render clock)
    • Note that interpolation only works on RigidBodies that the physics system moves algorithmically or using rb.MovePosition(). If your RigidBody is kinematic and you move it yourself, there will be no interpolation.
    Some things move in FixedUpdate (no interpolation), and others move in Update or LateUpdate:
    • Use SmartUpdate and LateUpdate in the Brain. SmartUpdate will update individual vcams depending on the motion of their targets (some in fixed, some in Late). LateUpdate for blending is the best compromise here, as there is no perfect solution
    • SmartUpdate is a good setting for initial development (that's why it's the default) but once the game begins to mature it's a good idea to get the movement under control and tune the camera for it

    The Blend Update method is supposed to only choose the clock on which to advance the blends. It's quite puzzling that this has an impact on the jitter in your case. It might be a bug. I will investigate.

    Unfortunately for now Cinemachine's damping algorithm is highly susceptible to framerate variability. If you have a custom camera script that doesn't suffer as much from this, you can still use it with Cinemachine and Timeline. Simply have your custom script control a passive CinemachineVirtualCamera (i.e. one with DoNothing in both Aim and Body) instead of the Unity Camera, and there you go, a custom vcam that moves the way you want it to and plays nicely with the other vcams. You can even add noise to it, and other CM extensions (like confiner, collider, impulse listener, postprocessing, etc).

    Finally, on the subject of deltaTime variation, this is something of a hot topic at Unity right now, and there are some forum threads on this. We think that the deltaTime guessing algorithm might be improved, which would significantly reduce many of the camera jitter problems that people often encounter.

    Again, sorry for the delayed response. I hope it helps clear some things up.
     
    Last edited: Apr 27, 2023
  39. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,726
    Update: there is indeed a bug in BlendUpdateMethod==LateUpdate, which could lead to judder in some cases. We will fix this for the next CM release.

    Many thanks to you for your perseverance in bringing this to our attention :)
     
    Lolka_Med and SirWhiteBeard like this.
  40. SirWhiteBeard

    SirWhiteBeard

    Joined:
    Feb 21, 2014
    Posts:
    66
    @Gregoryl first of all thank you for the amazing support on this topic, and I completely understand that this simply takes some time! Seriously, many thanks on the support.

    The explanation about the different clocks and FixedUpdate, Update and LateUpdate are really useful. Another thing that was of great value to me, and might be to others is the fact that you can mix Cinemachine camera's with your own custom camera scripts. I think this is something not alot of users know/have tried.
    Regarding the deltaTime variation, during my journey to find anything jitter relatable I came across some useful long topics on the Unity Forums, some of them are really complex/indepth.

    No thanks, I was just simply trying to fix something within my own project and learned alot during this process.

    I still have some small questions that are left unanswered during my journey;

    • Eventually this bug will be fixed in the next CM release, does this mean that in my scenario it's still best to leave both brain settings on FixedUpdate?
    • Something that came to mind was the following, I'm currently handeling everything in FixedUpdate (i.e. player movement, cameramovement) and my Fixed Timestep is 0,02 (default), which means there are 50 FixedUpdates per second (50 fps). Wouldn't this make it irrelevant if v-sync is turned on or off?
    • Another thing I see alot of different opinions on is changing the Fixed Timestep. Why is it's default 0,02 (50 fps) and not 0,01667 (60 fps)? And is it recommended to change the Fixed Timestep, or is it better to keep it at 0,02?
    Once again, many thanks for the support and I'm looking forward to the next CM release!
     
  41. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,726
    Bingo! You hit the jackpot. Stay tuned for updates on this one.

    Yes, if you continue to drive everything on FixedUpdate, that is your best option. The bug does not affect you in that case. After the bug is fixed, you should still leave that setting where it is.

    I'm not sure I understand the question. Unless render time and physics time by some co-incidence *exactly* match all the time, you will get aliasing. Vsync or no vsync.

    Short answer: I don't know. You have to experiment with it. One thing, though: don't set it too small or you'll kill performance.
     
  42. SirWhiteBeard

    SirWhiteBeard

    Joined:
    Feb 21, 2014
    Posts:
    66
    Thanks for the quick response!

    What I actually mean is, wouldn't it be redundant turning of v-sync since all gameplay runs in the FixedUpdate and is updated at 50fps.
     
  43. Freznosis

    Freznosis

    Joined:
    Jul 16, 2014
    Posts:
    298
    I've been having a similar problem with Cinemachine. I changed the damping on the vCam and it was indeed that. Was there any fixes for this in Cinemachine 2.5? I am using the latest version and still have problems with Jitter.

    I have a vCam following a rigidbody car. The car uses WheelColliders and every piece of physics code is FixedUpdate. No interpolation on the rigidbody. SmartUpdate makes the vCam always be set to FixedUpdate, and for the most part it's usually smooth and no problems. But I noticed if I turn off vsync, then the jitter gets very bad. And what's weird is that the jitter gets even worse if I manually set the brain to FixedUpdate?

    Here's a video.

    As you can see, the jitter doesn't always happen, and the transitions are smooth. It seems to happen every 2 minutes or so, and the higher the frame rate, the more often the jitters. My frame rate is always constant 100-110 fps, no spikes in the profiler, nothing out of the ordinary to cause a jump.
     
  44. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,726
    @Freznosis It's not Cinemachine, it's problems with the stability of Unity's framerate. The reason it seems to go away when you turn the damping down is that with damping on, the car will jump in the frame, while with the damping off the background will move irregularly, and the car jittering in the frame is far more visible to us.

    However, there is hope. This thread is all about irregular framerate, and Unity is taking it very seriously. There is an active effort being made to fix it.
     
    Emanx140 and Freznosis like this.
  45. Freznosis

    Freznosis

    Joined:
    Jul 16, 2014
    Posts:
    298
    That does make sense! Now that I've tested what you've said, I can see what you mean. When the camera is locked to the car, it's not so noticeable that the background is now slightly jittering. Thank you, I'll make sure to keep an eye out on that thread as it does seem to affect other things that aren't just the camera.

    In the meantime is there anything you recommend to help "hide" the problem while we wait for a proper fix? On reddit there are a handful of people that are lerping a hidden transform in LateUpdate that follows the main transform. Then setting Cinemachine to just use the hidden transform instead. It's kind of hacky but if that works in the meantime, I wouldn't mind doing something similar until we can get something proper from Unity.
     
    drzzzzz likes this.
  46. dantefabian

    dantefabian

    Joined:
    Jul 21, 2018
    Posts:
    1
    Wow thanks guys! I'm a newbie and this helped a lot with my project. I'm working on a 2D platformer and I was also experiencing jittering when moving to the left. My Healthbar was also flickering. At first I thought it has to do with the code transform.eulerAngles since its only happening when I'm moving to the left.
    My Player movement was a mix of Update and FixedUpdate. My Parallax Background was on FixedUpdate.
    My Healthbar was on LateUpdate and I turned Interpolation on to try to fix it. I also had Damping on. Yeah I know I'm a tool, lol!

    I was able to fix my project putting all Player and enemy movement on FixedUpdate. I kept the Jumping on Void Update though. Then I turned interpolation off and turned the Damping down.

    Now everything is running as smooth as silk. No more flickering Healthbar too. Thanks!
     
    Gregoryl likes this.
  47. chaosmonger

    chaosmonger

    Joined:
    Jan 23, 2019
    Posts:
    71
    I'm bring back this topic hoping for help... Maybe @Gregoryl can help somehow!
    So, the game is 2D, the camera must be Ortographic (can't change it to perspective for many reasons), I've a Parallax script in which I can change Update method. I've Cinemachine. I've a player which movements are in Update (and I cannot change that because I'll need to change tons of stuff, that for a parallax jittering is not worth).

    So, considering Player is in Update.
    I've tried every combination on changing the Cinemachine Brain Update Method and Blend Update Method, trying to match the ones of my Parallax, but, as per this thread, it's either my background or my player jittering, can't have both smooth (Player is smooth when Cinemachine Update Method is set to LateUpdate, Background is smooth when set to FixedUpdate).

    I've tried, just for the sake of it, to set my player movement handlers to FixedUpdate and it did work good. But, as I said, unfortunately I can't do that because it'll mean to change the whole architecture of my game and at this stage is not possible.

    My question is: isn't there really a way to fix the issue?
    A parallax script to handle the Cinemachine Brain to somehow solve my troubles? Or maybe something for the way the camera follows the player? I don't know...

    I'm open to suggestions. Thanks a lot!

    P.S. here my Parallax code:

    Code (CSharp):
    1. public class ParallaxElement : MonoBehaviour
    2.     {
    3.         /// the possible ticks at which this parallax element can update at
    4.         public enum UpdateModes { Update, LateUpdate, FixedUpdate }
    5.  
    6.         [Header("Behaviour")]
    7.         [MMInformation("This component will make this GameObject move in parallax (when the camera moves) if the camera's CameraController component has been set to move parallax elements. Here you can determine the relative horizontal and vertical speed, and in which direction the element should move.", MoreMountains.Tools.MMInformationAttribute.InformationType.Info, false)]
    8.         /// the selected update mode that will determine at which tick this parallax element will run
    9.         public UpdateModes UpdateMode = UpdateModes.LateUpdate;
    10.         /// horizontal speed of the layer
    11.         public float HorizontalSpeed;
    12.         /// vertical speed of the layer
    13.         public float VerticalSpeed;
    14.         /// defines if the layer moves in the same direction as the camera or not
    15.         public bool MoveInOppositeDirection = true;
    16.  
    17.         // private stuff
    18.         protected Vector3 _previousCameraPosition;
    19.         protected bool _previousMoveParallax;
    20.         protected ParallaxCamera _parallaxCamera;
    21.         protected Camera _camera;
    22.         protected Transform _cameraTransform;
    23.         protected Vector3 _difference;
    24.         protected Vector3 _speed;
    25.  
    26.         /// <summary>
    27.         /// Initialization
    28.         /// </summary>
    29.         protected virtual void OnEnable()
    30.         {
    31.             if (Camera.main == null)
    32.                 return;
    33.                
    34.             _camera = Camera.main;
    35.             if (_camera != null)
    36.             {
    37.                 _parallaxCamera = _camera.GetComponent<ParallaxCamera>();
    38.                 _cameraTransform = _camera.transform;      
    39.                 _previousCameraPosition = _cameraTransform.position;  
    40.             }
    41.         }
    42.  
    43.  
    44.         /// <summary>
    45.         /// On fixed update, we process our movement if needed
    46.         /// </summary>
    47.         protected virtual void FixedUpdate()
    48.         {
    49.             if (UpdateMode == UpdateModes.FixedUpdate)
    50.             {
    51.                 ProcessParallax();
    52.             }
    53.         }
    54.  
    55.  
    56.         /// <summary>
    57.         /// On update, we process our movement if needed
    58.         /// </summary>
    59.         protected virtual void Update()
    60.         {
    61.             if (UpdateMode == UpdateModes.Update)
    62.             {
    63.                 ProcessParallax();
    64.             }
    65.         }
    66.  
    67.         /// <summary>
    68.         /// On late update, we process our movement if needed
    69.         /// </summary>
    70.         protected virtual void LateUpdate ()
    71.         {
    72.             if (UpdateMode == UpdateModes.LateUpdate)
    73.             {
    74.                 ProcessParallax();
    75.             }
    76.         }
    77.  
    78.         /// <summary>
    79.         /// Every frame, we move the parallax layer according to the camera's position
    80.         /// </summary>
    81.         protected virtual void ProcessParallax()
    82.         {
    83.             if (_parallaxCamera == null)
    84.             {
    85.                 return;
    86.             }
    87.  
    88.             if (!Application.isPlaying && !_parallaxCamera.MoveParallax)
    89.             {
    90.                 return;
    91.             }
    92.  
    93.             if (_parallaxCamera.MoveParallax && !_previousMoveParallax)
    94.             {
    95.                 _previousCameraPosition = _cameraTransform.position;
    96.             }
    97.  
    98.             _previousMoveParallax = _parallaxCamera.MoveParallax;
    99.  
    100.             _speed.x = HorizontalSpeed;
    101.             _speed.y = VerticalSpeed;
    102.             _speed.z = 0f;
    103.  
    104.             _difference = _cameraTransform.position - _previousCameraPosition;
    105.             float direction = (MoveInOppositeDirection) ? -1f : 1f;
    106.             transform.position += Vector3.Scale(_difference, _speed) * direction;
    107.  
    108.             _previousCameraPosition = _cameraTransform.position;
    109.         }
    110.     }
     
  48. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,726
    I'm guessing that the problem comes from the parallax being updated before the camera is updated, so that the stale camera position from the previous frame is being used. Because the parallax depends on the camera position, you must update it after the camera is positioned. The camera is positioned in CinemachineBrain.LateUpdate().

    So:
    • Put character movement in Update.
    • Put the CM Brain in LateUpdate.
    • Put the parallax in LateUpdate.
    • Set the script execution order of ParallaxElement to update after CinemachineBrain.
     
  49. chaosmonger

    chaosmonger

    Joined:
    Jan 23, 2019
    Posts:
    71

    Thanks. I've tried but it messes things up... Not sure why, but if I give it a value of 101 for instance (or 401) to the ParallaxElement, things start acting weirdly... And, most of all, Parallax is not working at all.

    Or maybe I understood it wrongly, but if you meant to go in Project Settings/Script Execution Order, then yeah, doesn't work...
    Here a screenshot:

    (I've tried 101, 401 and 600... same result: weird behavior overall in various scripts, and Parallax not working) ?!?!?
     
  50. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,726
    It just has to be bigger than 100, so that ParallaxElement.LateUpdate is called after CinemachineBrain.LateUpdate. I don't see ParallaxElement in your screen shot. That could be why it's not working.

    Other than that, I don't know what to tell you, there might be some dependencies in your project that you're not detailing. You'll have to debug it.

    If you set it up the way I said, you should not have camera jitter.