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 Ball with rigidbody is stuttering/jittering

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

  1. mathiasbc04

    mathiasbc04

    Joined:
    Dec 21, 2020
    Posts:
    32


    Hi, I'm moving a ball with AddForce, but as you can see in the video the ball begins to stutter if it is moving fast. It isn't very noticable in the editor, but very much on my phone. I'm unsure if it's the Cinemachine camera or the script of the ball that is causing the problem.

    Here's the 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.  
    30.             fingerDown = true;
    31.         }
    32.         else
    33.         {
    34.             fingerDown = false;
    35.         }
    36.     }
    37.  
    38.     private bool OnGround()
    39.     {
    40.         Vector3 rayOrigin = transform.position;
    41.         float rayDistance = 0.8f;
    42.         LayerMask layerMask = LayerMask.GetMask("Ground");
    43.         RaycastHit hit;
    44.         if (Physics.Raycast(rayOrigin, Vector3.down, out hit, rayDistance, layerMask))
    45.         {
    46.             slopeNormal = hit.normal;
    47.             // Calculates the angle along z axis
    48.             slopeAngle = Vector2.Angle(Vector3.up, slopeNormal);
    49.  
    50.             return true;
    51.         }
    52.  
    53.         return false;
    54.     }
    55.  
    56.  
    57.     private void FixedUpdate()
    58.     {
    59.         if (fingerDown && move)
    60.         {
    61.             // Calculations to make it more responsive
    62.  
    63.             // calculate the direction we want to move in and our desired velocity
    64.             float targetSpeed = (xForce * sideSpeed);
    65.             // calculate the difference between current velocity and desired velocity
    66.             float speedDif = targetSpeed - rb.velocity.x;
    67.             // Change acceleration rate depending on situation
    68.             float accelRate = (Mathf.Abs(targetSpeed) > 0.01f) ? acceleration : decceleration;
    69.             // Applies acceleration to speed difference, then raises to a set power so acceleration increases with higher speeds
    70.             // finally multiplies by sign to reapply direction
    71.             float movement = Mathf.Pow(Mathf.Abs(speedDif) * accelRate, velPower) * Mathf.Sign(speedDif);
    72.  
    73.  
    74.             // Making the ball move along a slope
    75.            
    76.             if(OnGround())
    77.             {
    78.                 forceDirection = Vector3.ProjectOnPlane(new Vector3(movement, 0, 0), slopeNormal);
    79.             }
    80.             else
    81.             {
    82.                 forceDirection = new Vector3(movement, 0, 0);
    83.             }
    84.  
    85.             // Makes the ball move from left ot right
    86.             rb.AddForce(new Vector3(forceDirection.x, forceDirection.y, 0));
    87.         }
    88.  
    89.         // Move forward
    90.         if (move)
    91.         {
    92.             if (rb.velocity.z < maxForwardSpeed)
    93.             {
    94.                 rb.AddForce(Vector3.forward * forwardSpeed * Time.fixedDeltaTime);
    95.             }
    96.         }
    97.  
    98.  
    99.     }
     
  2. arkano22

    arkano22

    Joined:
    Sep 20, 2012
    Posts:
    1,630
    Make sure your rigidbody is using interpolation. Otherwise your ball's transform will only be updated in frames where FixedUpdate() is called.
     
  3. mathiasbc04

    mathiasbc04

    Joined:
    Dec 21, 2020
    Posts:
    32
    Yes it is set to "interpolate"
     
  4. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    10,468
    I have no idea what/why you're seeing jittering but a quick unrelated observation is that you should not scale the force by the fixed-update interval; it'll already have that done (force will be time-integrated to velocity change) when the force is applied so essentially your force is being scaled down twice. You only do this on one, no idea why.
     
    arkano22 likes this.
  5. mathiasbc04

    mathiasbc04

    Joined:
    Dec 21, 2020
    Posts:
    32
    Alright so I should remove the fixedDeltaTime?
     
  6. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    10,468
    I said that yes.
     
  7. mathiasbc04

    mathiasbc04

    Joined:
    Dec 21, 2020
    Posts:
    32
    Do you see some more errors in the script? I'm not sure if I put the correct things inside Update() or FixedUpdate(). I tried moving the "// Calculations to make it more responsive" inside the Update() method, but that didn't help.
     
  8. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    10,468
    I have no idea what the problem is, sorry.

    You need to start reducing the problem space. For instance, finding if it's related to physics by not adding forces left/right, remove the landscape and just move it forward by setting the velocity once, changing the method of the camera that tracks it (discount cinemachine) etc.
     
  9. Unifikation

    Unifikation

    Joined:
    Jan 4, 2023
    Posts:
    1,026
    It's hard to tell in the video, but I think the issues are in Cinemachine. @Gregoryl could you break down the differences between fixedUpdate, LateUpdate and the other option in Cinemachine. I think this is one of the times that's an issue.

    How/Why I think this: I put my finger over the ball whilst watching the video, so that I wasn't distracted by its judder, and could still detect the same sort of pattern of judders in the geometry passing by.
     
  10. mathiasbc04

    mathiasbc04

    Joined:
    Dec 21, 2020
    Posts:
    32
    I tried turning off interpolation and now the stuttering is gone
     
  11. Unifikation

    Unifikation

    Joined:
    Jan 4, 2023
    Posts:
    1,026
    Can someone else explain why this works for this problem?

    I'd have thought that interpolation on would be the saving grave, not turning it off. But what do I know?
     
  12. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,207
    Turning off interpolation means that the camera will be updating on the same clock as the ball: the physics clock (assuming the brain is SmartUpdate). With interpolation ON, ball's movement gets "converted" to values suitable for the render clock, and CM will also track on that clock. Normally this works fine. The symptoms here indicate to me that for some reason interpolation is not functioning correctly in this case on this platform. I don't know why.
     
    Last edited: Jun 23, 2023
  13. Edy

    Edy

    Joined:
    Jun 3, 2010
    Posts:
    2,423
    Last time I checked Cinemachine the "SmartUpdate" option just checked if the target GameObject has a rigidbody or not to decide whether update the camera in Update or FixedUpdate. It didn't checked whether the Rigidbody has interpolation enabled or not. Even if CM does that now, this approach wouldn't work when the target GameObject is a child GameObject of the Rigidbody object.

    As for a proper solution to the stuttering problem, I'd try forcing Cinemachine to update the camera in the Update method and enable interpolation in the Rigidbody.
     
  14. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,207
    Not true. Cinemachine SmartUpdate tracks when the target transform gets changed: if the transform changes only in FixedUpdate then the vcam will update in FixedUpdate. If the transform changes outside of FixedUpdate, the vcam will update in LateUpdate.
     
    Edy likes this.
  15. Edy

    Edy

    Joined:
    Jun 3, 2010
    Posts:
    2,423
    Correct, it must have been an older version of Cinemachine (in Unity 2019), sorry. I recall seeing the code that just checked for the presence of a Rigidbody in order to use FixedUpdate or LateUpdate. Glad to know this part has improved!
     
    Last edited: Jun 24, 2023