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. Dismiss Notice

Bug Cinemachine is stuttering/jittering when following ball with rigidbody

Discussion in 'Cinemachine' started by mathiasbc04, Jun 21, 2023.

  1. mathiasbc04

    mathiasbc04

    Joined:
    Dec 21, 2020
    Posts:
    32


    The faster the ball goes the more it stutters. In the editor it's not very visible, but very much on my phone. The "Update Method" is set to "Smart Update". If I set it to "Late Update" nothing changes, and if I set it to "Fixed Update" it stutters even more. The body is set to Framing Transposer. I'm unsure if it's the camera or the script that is causing the issue though. Here's the movement script:

    Code (CSharp):
    1.     private void Update()
    2.     {
    3.         if (Input.touchCount > 0)
    4.         {
    5.             Touch touch = Input.GetTouch(0);
    6.  
    7.             switch (touch.phase)
    8.             {
    9.                 case TouchPhase.Began:
    10.                     startPosition = touch.position;
    11.                     break;
    12.                 case TouchPhase.Moved:
    13.                     // The force on the x axis is calculated...
    14.                     // by how far away the finger is from the starting point
    15.                     xForce = touch.position.x - startPosition.x;
    16.  
    17.                     // Limit x-axis force to prevent advantages from longer screens
    18.                     if (xForce > maxXForce)
    19.                     {
    20.                         xForce = maxXForce;
    21.                     }
    22.                     else if (xForce < -maxXForce)
    23.                     {
    24.                         xForce = -maxXForce;
    25.                     }
    26.                     break;
    27.             }
    28.  
    29.             fingerDown = true;
    30.         }
    31.         else
    32.         {
    33.             fingerDown = false;
    34.         }
    35.     }
    36.  
    37.     private bool OnGround()
    38.     {
    39.         Vector3 rayOrigin = transform.position;
    40.         float rayDistance = 0.8f;
    41.         LayerMask layerMask = LayerMask.GetMask("Ground");
    42.         RaycastHit hit;
    43.         if (Physics.Raycast(rayOrigin, Vector3.down, out hit, rayDistance, layerMask))
    44.         {
    45.             slopeNormal = hit.normal;
    46.             // Calculates the angle along z axis
    47.             slopeAngle = Vector2.Angle(Vector3.up, slopeNormal);
    48.  
    49.             return true;
    50.         }
    51.  
    52.         return false;
    53.     }
    54.  
    55.  
    56.     private void FixedUpdate()
    57.     {
    58.         if (fingerDown && move)
    59.         {
    60.             // Calculations to make it more responsive
    61.  
    62.             // calculate the direction we want to move in and our desired velocity
    63.             float targetSpeed = (xForce * sideSpeed);
    64.             // calculate the difference between current velocity and desired velocity
    65.             float speedDif = targetSpeed - rb.velocity.x;
    66.             // Change acceleration rate depending on situation
    67.             float accelRate = (Mathf.Abs(targetSpeed) > 0.01f) ? acceleration : decceleration;
    68.             // Applies acceleration to speed difference, then raises to a set power so acceleration increases with higher speeds
    69.             // finally multiplies by sign to reapply direction
    70.             float movement = Mathf.Pow(Mathf.Abs(speedDif) * accelRate, velPower) * Mathf.Sign(speedDif);
    71.  
    72.  
    73.             // Making the ball move along a slope
    74.            
    75.             if(OnGround())
    76.             {
    77.                 forceDirection = Vector3.ProjectOnPlane(new Vector3(movement, 0, 0), slopeNormal);
    78.             }
    79.             else
    80.             {
    81.                 forceDirection = new Vector3(movement, 0, 0);
    82.             }
    83.  
    84.             // Makes the ball move from left ot right
    85.             rb.AddForce(new Vector3(forceDirection.x, forceDirection.y, 0));
    86.         }
    87.  
    88.         // Move forward
    89.         if (move)
    90.         {
    91.             if (rb.velocity.z < maxForwardSpeed)
    92.             {
    93.                 rb.AddForce(Vector3.forward * forwardSpeed * Time.fixedDeltaTime);
    94.             }
    95.         }
    96.  
    97.     }
     
  2. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,207
    Do you have Interpolation enabled on the ball?
    Can you show the vcam inspector?
    What version of Cinemachine?
     
  3. mathiasbc04

    mathiasbc04

    Joined:
    Dec 21, 2020
    Posts:
    32
    1. Yes
    2.
    3. The version is 2.8.9

    By the way if I set the damping to 0 the stuttering can't be seen, but I know that is pretty bad fix.
     
  4. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,207
    If the stutter goes away when you remove the camera damping, that's a pretty strong sign that the ball is not moving in sync with the render clock. This could indicate that interpolation is not working properly. I'm not a PhysX expert, but superficially your script looks ok to me. Is that 100% the only movement being applied to the ball?

    Try this experiment: set the Brain to SmartUpdate, and turn off the interpolation on the ball. Run the game, and while the ball is moving took at the vcam inspector at the top, to the right of the Solo button. It will indicate LateUpdate or FixedUpdate, depending on how the vcam is tracking the ball. What does it say?
     
  5. mathiasbc04

    mathiasbc04

    Joined:
    Dec 21, 2020
    Posts:
    32
    Yes that's the only movement being applied to the ball. The vcam says FixedUpdate
     
  6. mathiasbc04

    mathiasbc04

    Joined:
    Dec 21, 2020
    Posts:
    32
    I tested the game on my phone with interpolate set to none and now there's no stuttering???
     
  7. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,207
    ok, if all else fails, that is a potential solution for you.

    What it means is that interpolation is not functioning correctly on the phone. You might try asking why on the physics forum, because your code looks correct to me.
     
  8. mathiasbc04

    mathiasbc04

    Joined:
    Dec 21, 2020
    Posts:
    32
    Many people say that interpolation should be turned on, but is it okay to have it turned off? And if it is turned off does it make the ball move less smooth?
     
  9. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,207
    It's suboptimal because there might be aliasing between physics frames and render frames, but many people find this to be acceptable.
     
  10. mathiasbc04

    mathiasbc04

    Joined:
    Dec 21, 2020
    Posts:
    32
    I noticed that if I turn interpolation off, I have to set the update method to FixedUpdate or else it will jitter. But if I turn it on, I have to set the update method to LateUpdate or else it will jitter. (With interpolation on and LateUpdate there is still jittering, but it's not as visible). Why is that?
     
  11. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,207
    For the physics simulation to function correctly, it needs to simulate at fixed time intervals, but Unity renders frames at variable time intervals, which do not in general fall on fixed-frame boundaries. Sometimes a render frame will span one physics frame, sometimes 2, sometimes none, and so on. It depends on the environment and the on the fixed timestep - which is what in your project, btw? Unless the camera is also tracking on the fixedUpdate clock, this will read as jitter of the ball in the render frame. If the camera moves in sync with the ball, the ball will appear steady in the frame, although if you look carefully you will see that the background can be jittery in this situation, but this is much less bothersome to the viewer.

    Interpolation simulates physics one frame ahead and, before Update is called, pokes the transform with a value computed by interpolating the last 2 physics frames by an amount that corresponds to where the render frame falls. This creates smooth movement from the point of view of the render frames, and cameras tracking in Update or LateUpdate will track the ball smoothly.

    Normally this functions very well. The fact that it's a little jittery in your case suggests to me that Interpolation is not quite working properly, or that you have some other factor interfering with the transforms, or that your movement code is not moving the ball smoothly (maybe the force you apply is very jittery). Can you try replacing your movement code with something that's guaranteed to be smooth?
     
  12. mathiasbc04

    mathiasbc04

    Joined:
    Dec 21, 2020
    Posts:
    32
    My fixed timestep was 0.02, but I just changed it to 0.01 now that interpolation is turned off. As I mentioned before the jittering disappears when I disable interpolation. But when it's turned off the ball becomes less smooth. So when I set the fixed timestep to 0.01 it becomes smooth again and it seems to fix my problem. I just hope this doesn't have a major impact on the performance of my game.