Search Unity

  1. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Weird Stuttering With Camera [SOLVED]

Discussion in 'Physics' started by Agilapathy, Jul 29, 2018.

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

    Agilapathy

    Joined:
    Jun 29, 2018
    Posts:
    21
    Hi!

    I made a post about this problem of mine before, but got no answers. :(

    So I decided to try my best to dig into the problem with the help of Google and I think I've made some significant progress! :D

    I've simplified my camera rotation code and have made the hierarchy much simpler than it was before. (Which was probably scaring off people from my previous post. :confused:)

    The just of my system includes an object and camera. These objects are NOT parented in any way:

    upload_2018-7-28_14-13-19.png

    The object has a script attached that creates player movement (I feel that this script may not be the problem, but I included it anyways just in case):
    upload_2018-7-28_14-16-18.png
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class Player : MonoBehaviour {
    6.  
    7.     static Animator anim;
    8.  
    9.     public float speed = 1.07f;
    10.     public float runMultiplier = 1.5f;
    11.     public float jumpHeight = 0.91f;
    12.     public float distanceFromGroundUntilNextJump = 0.28f;
    13.     public float maxSpeed = 1f;
    14.     public Rigidbody rigidBody;
    15.  
    16.     enum Speed { Slow, Regular };
    17.     Speed playerSpeed = Speed.Regular;
    18.  
    19.     float varyingMaxSpeed;
    20.     float varyingSpeed;
    21.  
    22.     bool running = false;
    23.     bool isGrounded = false;
    24.     bool wasHoldingShift = false;
    25.  
    26.     float animX;
    27.     float animY;
    28.  
    29.     void Start () {
    30.  
    31.         // I made the player visual invisible and the player controller visible for the sake of simplicity.
    32.         anim = GameObject.Find("PlayerVisual").GetComponent<Animator>();
    33.  
    34.         varyingMaxSpeed = maxSpeed;
    35.         varyingSpeed = speed;
    36.  
    37.     }
    38.  
    39.  
    40.     void FixedUpdate()
    41.     {
    42.         Animation();
    43.         CheckRunning();
    44.         Movement();
    45.         checkGround();
    46.     }
    47.  
    48.     void Animation()
    49.     {
    50.         if (running)
    51.         {
    52.             animX = Input.GetAxis("Horizontal4Anim");
    53.             animY = Input.GetAxis("Vertical4Anim");
    54.         }
    55.         else
    56.         {
    57.             animX = Input.GetAxis("Horizontal4Anim") * 0.5f;
    58.             animY = Input.GetAxis("Vertical4Anim") * 0.5f;
    59.         }
    60.  
    61.         anim.SetFloat("MoveX", animX, 0.1f, Time.deltaTime);
    62.         anim.SetFloat("MoveY", animY, 0.1f, Time.deltaTime);
    63.     }
    64.  
    65.     void Movement()
    66.     {
    67.  
    68.         if (!keyDown())
    69.         {
    70.             varyingMaxSpeed = 0.0f;
    71.         }
    72.  
    73.         switch (playerSpeed)
    74.         {
    75.             case Speed.Regular:
    76.  
    77.                 rigidBody.AddRelativeForce(new Vector3(Input.GetAxis("Horizontal") * varyingSpeed, 0.0f, Input.GetAxis("Vertical") * varyingSpeed) * Time.deltaTime);
    78.  
    79.                 if (running)
    80.                 {
    81.                     varyingMaxSpeed = maxSpeed * runMultiplier;
    82.                     varyingSpeed = speed * runMultiplier;
    83.                 }
    84.                 else
    85.                 {
    86.                     varyingMaxSpeed = maxSpeed;
    87.                     varyingSpeed = speed;
    88.                 }
    89.  
    90.                 break;
    91.             case Speed.Slow:
    92.  
    93.                 rigidBody.AddRelativeForce(new Vector3(Input.GetAxis("Horizontal") * varyingSpeed * 0.17f, 0.0f, Input.GetAxis("Vertical") * varyingSpeed * 0.17f) * Time.deltaTime);
    94.  
    95.                 if (running)
    96.                 {
    97.                     varyingMaxSpeed = maxSpeed * runMultiplier;
    98.                     varyingSpeed = speed * runMultiplier;
    99.                 }
    100.                 else
    101.                 {
    102.                     varyingMaxSpeed = maxSpeed;
    103.                     varyingSpeed = speed;
    104.                 }
    105.  
    106.                 break;
    107.         }
    108.  
    109.         float yCache = rigidBody.velocity.y;
    110.         rigidBody.velocity = new Vector3(rigidBody.velocity.x, 0.0f, rigidBody.velocity.z);
    111.         rigidBody.velocity = Vector3.ClampMagnitude(rigidBody.velocity, varyingMaxSpeed);
    112.         rigidBody.velocity = new Vector3(rigidBody.velocity.x, yCache, rigidBody.velocity.z);
    113.  
    114.         if (isGrounded == true)
    115.         {
    116.  
    117.             if (!keyDown())
    118.             {
    119.                 float curSpeed = rigidBody.velocity.magnitude;
    120.                 float newSpeed = curSpeed - 53f * Time.deltaTime;
    121.                 if(newSpeed < 0.0f)
    122.                 {
    123.                     newSpeed = 0.0f;
    124.                 }
    125.  
    126.                 rigidBody.velocity = rigidBody.velocity.normalized * newSpeed;
    127.             }
    128.  
    129.             playerSpeed = Speed.Regular;
    130.  
    131.             if (Input.GetButton("Jump"))
    132.             {
    133.  
    134.                 anim.SetBool("Jumping", true);
    135.                 rigidBody.velocity = new Vector3(rigidBody.velocity.x, 0.0f, rigidBody.velocity.z);
    136.                 rigidBody.AddForce(0.0f, jumpHeight / 4, 0.0f);
    137.  
    138.                 if (!keyDown())
    139.                 {
    140.                     rigidBody.velocity = new Vector3(rigidBody.velocity.x * 0.7f, rigidBody.velocity.y, rigidBody.velocity.z * 0.7f);
    141.  
    142.                 }
    143.             }
    144.         }
    145.         else
    146.         {
    147.             playerSpeed = Speed.Slow;
    148.         }
    149.     }
    150.  
    151.     void checkGround()
    152.     {
    153.         if (Physics.Raycast(gameObject.transform.position, Vector3.down, distanceFromGroundUntilNextJump))
    154.         {
    155.  
    156.             rigidBody.velocity = new Vector3(rigidBody.velocity.x, 0.0f, rigidBody.velocity.z);
    157.  
    158.             isGrounded = true;
    159.  
    160.             if (anim.GetBool("Jumping"))
    161.             {
    162.                 anim.SetBool("Jumping", false);
    163.             }
    164.  
    165.         }
    166.         else
    167.         {
    168.  
    169.             isGrounded = false;
    170.         }
    171.     }
    172.  
    173.     bool keyDown()
    174.     {
    175.         return (Input.GetAxis("Vertical") > 0.2f || Input.GetAxis("Vertical") < -0.2f || Input.GetAxis("Horizontal") > 0.2f || Input.GetAxis("Horizontal") < -0.2f);
    176.     }
    177.  
    178.     void CheckRunning()
    179.     {
    180.  
    181.         if (Input.GetButton("RunCont"))
    182.         {
    183.             running = true;
    184.         }
    185.  
    186.         if (Input.GetButton("Run"))
    187.         {
    188.             running = true;
    189.             wasHoldingShift = true;
    190.  
    191.         }
    192.         else if (!Input.GetButton("Run") && wasHoldingShift)
    193.         {
    194.             running = false;
    195.             wasHoldingShift = false;
    196.  
    197.         }
    198.     }
    199. }
    200.  
    The camera has a script attached that deals with the camera's movement (This is where I believe the problem lies.):
    upload_2018-7-28_14-20-21.png
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class TPC : MonoBehaviour {
    6.  
    7.     //The object that the camera will be looking at. (The Player.)
    8.     public Transform lookAt;
    9.  
    10.     //The minimum distance that the camera can go. (For camera collisions.)
    11.     public float minimumDistance = 1.0f;
    12.  
    13.     //The maximum distance that the camera can go. (For camera collisions.)
    14.     public float maximumDistance = 5.0f;
    15.  
    16.     //How smooth the transition is between distances.
    17.     public float distanceSmoothing = 10.0f;
    18.  
    19.     //How far the player can rotate the camera up.
    20.     public float minimumAngle = -80.0f;
    21.  
    22.     //How far the player can rotate the camera down.
    23.     public float maximumAngle = 80.0f;
    24.  
    25.     //How much your mouse movement influences
    26.     public float sensitivity = 1.0f;
    27.  
    28.     //Determines whether the mouse controls return opposite values.
    29.     public bool invertedLook = false;
    30.  
    31.     //The paramater that will determine the final distance value for the camera.
    32.     private float distance = 0.0f;
    33.  
    34.     //Returns the updated calculated distance value. (I have 2 values for distance in order to add a smoothing function.)
    35.     private float newDistance = 0.0f;
    36.  
    37.     //The mouse positions on the x and y axes.
    38.     private float currentX = 0.0f;
    39.     private float currentY = 0.0f;
    40.  
    41.     private void Start()
    42.     {
    43.  
    44.         //Makes sure that the cursor doesn't move.
    45.         Cursor.lockState = CursorLockMode.Locked;
    46.  
    47.         //Makes sure the cursor is invisible.
    48.         Cursor.visible = false;
    49.  
    50.     }
    51.  
    52.     private void Update()
    53.     {
    54.  
    55.         //Inverted Mouse mode on/off.
    56.         if (invertedLook)
    57.         {
    58.             currentX += -Input.GetAxis("Mouse X") * sensitivity;
    59.             currentY += Input.GetAxis("Mouse Y") * sensitivity;
    60.         } else
    61.         {
    62.             currentX += Input.GetAxis("Mouse X") * sensitivity;
    63.             currentY += -Input.GetAxis("Mouse Y") * sensitivity;
    64.         }
    65.  
    66.         //Limit how much the player can see up and down.
    67.         currentY = Mathf.Clamp(currentY, minimumAngle, maximumAngle);
    68.     }
    69.  
    70.     private void LateUpdate()
    71.     {
    72.         //Make a rotation value corresponding to the mouse movement that will be used for a couple calculations.
    73.         Quaternion rotation = Quaternion.Euler(currentY, currentX, 0);
    74.  
    75.         //Gets the position of the maximum distance that the camera can go from the player.
    76.         Vector3 maxDisCheck = new Vector3(0, 0, -maximumDistance);
    77.         Vector3 desiredCameraPos = lookAt.position + rotation * maxDisCheck;
    78.  
    79.         RaycastHit hit;
    80.  
    81.         //Makes a raycast between the camera's current position and the farthest position.
    82.         if (Physics.Linecast(lookAt.position, desiredCameraPos, out hit))
    83.          {
    84.             //If there's something in between those points, set the new distance to the distance between the player and where the raycast hit.
    85.              newDistance = Mathf.Clamp(hit.distance * 0.6f, minimumDistance, maximumDistance);
    86.          }
    87.          else
    88.         {
    89.             // If there isn't, then just set the new distance to as far as it can go, because theres nothing stopping it from going that far.
    90.             newDistance = maximumDistance;
    91.         }
    92.  
    93.         //Make the real distance variable equal to the new distance variable, but with a lerp to make it a smooth transition.
    94.         distance = Mathf.Lerp(distance, newDistance, Time.deltaTime * distanceSmoothing);
    95.  
    96.         //Set the position of the camera much similar to the desiredCameraPos variable, but instead of using the maximum distance, use the calculated distance variable.
    97.         Vector3 direction = new Vector3(0, 0, -distance);
    98.         transform.position = lookAt.position + rotation * direction;
    99.         transform.LookAt(lookAt.position);
    100.  
    101.         //Allow the "MouseX" value to determine the y rotation of the player.
    102.         lookAt.transform.rotation = Quaternion.Euler(lookAt.transform.rotation.x, currentX, lookAt.transform.rotation.z);
    103.  
    104.     }
    105. }
    106.  

    I cannot provide a video of whats happening because the frame rate of the video would have to be EXACTLY the same as the game to see the effect. (Which is impossible for me.)

    The camera is sort of stuttering when it moves without turning the camera, but is most noticeable when I circle objects.

    I've been on this problem for about half a month now and it really puts a roadblock in my game's development. If anyone has the slightest idea of whats going on, ANY help will be much appreciated! :D

    Thank you! :D
     
  2. Antypodish

    Antypodish

    Joined:
    Apr 29, 2014
    Posts:
    10,726
    I run your camera script and see no issue.
    Did you run your camera script in editor?
    Try create new game window, outside main unity work space. Separate it.
    And try build a game, to see, if the stuttering exists.
    Editor itself can create some lag spikes.
     
  3. Agilapathy

    Agilapathy

    Joined:
    Jun 29, 2018
    Posts:
    21
    I built and ran the game and got the same results.

    I've realized throughout the many tests that I conducted that the root of the problem exists not within the camera script, but how the camera and the player interact. If I control the movement of the player with transform.Translate(), the shakiness is gone, but when I control it with rigidBody.AddForce() or rigidBody.AddRelativeForce(), the shakiness appears. Throughout all of this, the camera's script remains the same. I've seen many problems with using transform.Translate() to move characters, so that's not an option for me. I've also tried changing things with interpolation and continuous, discrete, and continuous dynamic collision detection, and unless there's a specific combination of those settings, (which I think I've tried them all) that doesn't work either. :confused:
     
  4. Antypodish

    Antypodish

    Joined:
    Apr 29, 2014
    Posts:
    10,726
    Try put all physics movement on the same update Unity clock.
    Movements and physics should be on FixedUpdate.
     
  5. Agilapathy

    Agilapathy

    Joined:
    Jun 29, 2018
    Posts:
    21
    I've done that, they're all called in the FixedUpdate method, they're just put into "sections" (Different methods) for organization purposes, unless you were talking about the camera movement too, I've done a test on that and I get the same results.

    P.S. I have tried putting both the movement and the camera controls in FixedUpdate, and it does technically "remove the stuttering", but by spreading the stuttering out by emulating reduced frame rate. (The game looks as if its running at 30 fps all the time.) It was a solution with a nasty price, so I avoided it.
     
  6. Antypodish

    Antypodish

    Joined:
    Apr 29, 2014
    Posts:
    10,726
    Have you looked carefully in the editor, what is actually shaking? camera or object (s)?
    Because if camera is in separate script, it should not be affected. Unless is on wring frequency.
     
  7. Timato0

    Timato0

    Joined:
    Feb 27, 2018
    Posts:
    6
    By "stutter" are you implying that the camera looks jittery or that it is doing something else? I noticed that you are lerping a distance to move the camera, have you considered simply using SmoothDamp() instead? In my experience that gives rather clean camera motion.
     
  8. Agilapathy

    Agilapathy

    Joined:
    Jun 29, 2018
    Posts:
    21
    I sincerely apologize for the late response. I was studding for my final that I just got done today. (Thank god. :confused:)

    I think I made the mistake of not attaching the actual project file so that you can see what I mean.

    Here it is:
    OSOC.zip

    By the way I integrated Timato0's idea of using SmoothDamp(). Unfortunately it didn't get rid of the stutter, but I have seen videos say in fact that using Lerp() to move cameras can be unstable. So it did fix something and if not, it fixed a problem that I would most likely run into in the future. Thank you for that! :D
     

    Attached Files:

  9. Agilapathy

    Agilapathy

    Joined:
    Jun 29, 2018
    Posts:
    21
    Bump

    I'm still trying to figure this out! Please help someone. :(
     
  10. Marcos-Schultz

    Marcos-Schultz

    Joined:
    Feb 24, 2014
    Posts:
    381
  11. Agilapathy

    Agilapathy

    Joined:
    Jun 29, 2018
    Posts:
    21
    I still get the same shaking problem, even when I moved my character with the simplest AddRelativeForce code:
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class PlayerTEST : MonoBehaviour {
    6.  
    7.     Rigidbody rigidBody;
    8.     public float speed = 0.0f;
    9.  
    10.     // Use this for initialization
    11.     void Start () {
    12.  
    13.         rigidBody = gameObject.GetComponent<Rigidbody>();
    14.     }
    15.    
    16.     // Update is called once per frame
    17.     void FixedUpdate () {
    18.  
    19.  
    20.         rigidBody.AddRelativeForce(new Vector3(Input.GetAxis("Horizontal") * speed, 0.0f, Input.GetAxis("Vertical") * speed));
    21.         rigidBody.AddRelativeForce(new Vector3(Input.GetAxis("Horizontal") * speed, 0.0f, Input.GetAxis("Vertical") * speed));
    22.     }
    23. }
    24.  
     
  12. Agilapathy

    Agilapathy

    Joined:
    Jun 29, 2018
    Posts:
    21
    Bump

    I made a REALLY REALLY REALLY simplified version of my problem in a new project in hopes that someone can help me. Here it is:

    Camera Stutter Issue.zip
     

    Attached Files:

  13. Antypodish

    Antypodish

    Joined:
    Apr 29, 2014
    Posts:
    10,726
    Try replace
    void LateUpdate ()
    with
    void FixedUpdate ()

    and see if any better
     
    Last edited: Apr 7, 2019
  14. Agilapathy

    Agilapathy

    Joined:
    Jun 29, 2018
    Posts:
    21
    I finally figured it out.

    I went to Edit > Project Settings > Time and changed the "Fixed Timestep" from 0.02 to 0.005

    Apparently I've been experiencing a bug that Unity hasn't squashed yet. ¯\_(ツ)_/¯

    Other than that thank you all for your attempts, I really appreciate it!

    Cheers!
     
  15. Antypodish

    Antypodish

    Joined:
    Apr 29, 2014
    Posts:
    10,726
    You should read upon implication of.
    Increasing FixedTime step frequency.
    You are likely will run soon int major performance hit, once adding more objects.

    Did you try my suggestion?
     
    devotid likes this.
  16. Agilapathy

    Agilapathy

    Joined:
    Jun 29, 2018
    Posts:
    21
    Yes, unfortunately I've tried that before with no luck as well as with every other update method.
     
  17. tataygames

    tataygames

    Joined:
    Aug 4, 2016
    Posts:
    55
    Im having difficulty in unity 2018.3
    this version has lots of bugs, the movement is stuttering having your camera followed the gameobject your camera will stutter too, if you dont use Vector3.SmoothDamp

    I tried many ways, time.deltatime, time.fixeddeltatime, translate, all of that stutter, in the update and in fixedupdate.

    and the new prefab system consumes you lots of clicks and entering inside a prefab is a waste of time.
     
    fsajjan likes this.
  18. Sluggy

    Sluggy

    Joined:
    Nov 27, 2012
    Posts:
    941
    Reducing the physics timestep is not the recommended way to solve this issue, nor is moving your camera movement code into FixedUpdate. This is a common problem that occurs with all computer graphics due to the instantaneous and discrete nature of rendering. You can get more detailed information from this site http://www.kinematicsoup.com/news/2016/8/9/rrypp5tkubynjwxhxjzd42s3o034o8

    The end solution is to use some kind of interpolation on both the camera and the graphical representation of the player. The camera itself needs to be interpolated so that the slightly jerky motion of the player character get smoothed out. On top of that you need to separate the rendered object that represents the player (the avatar as I'll refer to it) from the physical one that the player is controlling (the controller as I'll refer to it). The avatar object also should be interpolated as it needs to be moving smoothly rather than with the slightly jerky fixed motion that the physics simulation will have. I suppose an alternative would be to simply smooth the avatar object and then have the camera follow that in LateUpdate(). Haven't tried it that way myself but I don't see why it wouldn't work. The tricky part will be how you handle interpolating the avatar. If you want to keep it parented to the controller object you'll need to take that into account, otherwise you could have it as a separate object that smoothly follows the controller instead
     
  19. BastingQuill

    BastingQuill

    Joined:
    Jun 30, 2020
    Posts:
    2
    Had the same problem and I fixed it by just decreasing the Clipping planes from the Camera. Hope it helps! Two years after lol
     
    Godbout2 and AssortedNoodles like this.
  20. MasonAmadeus

    MasonAmadeus

    Joined:
    Dec 17, 2020
    Posts:
    1
    Oh. My. God.

    I have been slamming my head against my desk trying to figure out this exact same issue for way too long. I feel like I must have googled every combination of keywords possible. THIS fixed it for me. I dropped the far clipping plane from 1000 to 800 and BANG. Right there.

    BastingQuill, thank you so much.
     
  21. ejahgamer

    ejahgamer

    Joined:
    Jun 27, 2021
    Posts:
    1
    oh my god, I love you guys.... reducing the far clipping panes on my camera fixed this issue, now my linerenderer laser beam effect is working perfectly with no strange scan line type of effect!!!!! <3
     
  22. FissicsPeep

    FissicsPeep

    Joined:
    Jan 14, 2014
    Posts:
    79
    What? Reducing the clipping planes makes no sense. Would love someone from Unity to explain why that fixed the issue for the above 3 people :D
     
  23. Zimbres

    Zimbres

    Joined:
    Nov 17, 2014
    Posts:
    180
    did not worked for me. It's Far Clipping decreased + something else?
     
  24. FissicsPeep

    FissicsPeep

    Joined:
    Jan 14, 2014
    Posts:
    79
    I found what was causing mine, and this might be the same as for others.

    In the Input Manager, I had add an extra entry for my camera, which was mouse X. However, the sensitivity was set to 1000... way too high. Reducing this right down to less than 0.1, hugely improves things, even if you now need to move the mouse further.
     
Thread Status:
Not open for further replies.