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

the camera is stuttering, and i just cant fix it.

Discussion in 'Scripting' started by cyudani, Jan 6, 2022.

  1. cyudani

    cyudani

    Joined:
    Mar 25, 2021
    Posts:
    7
    hello everyone,
    i made a simple script that makes my camera do two things:
    1) rotate to look at one point
    2) move using Vector3.slerp between two points

    so i made the code and i worked great except the problem of stuttering effect that happends,
    i built the game. used late update , tested every function alone and of course searched on the net for a sulution, but i cant understand whats wrong, please help me!

    this is the code:


    Code (CSharp):
    1.  
    2. using UnityEngine;
    3.  
    4. public class CameraScript1 : MonoBehaviour
    5. {
    6.     public Transform lookAt, startRot, endRot;
    7.     float moveTime = 30f;
    8.     float startTime, fracComplete;
    9.     // Start is called before the first frame update
    10.     void Start()
    11.     {
    12.         startTime = Time.time;
    13.     }
    14.  
    15.     // Update is called once per frame
    16.  
    17.     void LateUpdate()
    18.     {
    19.         MovmentInTwoPoints();
    20.         rotateToward();
    21.      
    22.  
    23.     }
    24.  
    25.     void rotateToward()
    26.     {
    27.         Vector3 targetDir = lookAt.position - transform.position;
    28.         float angle = Time.deltaTime * 360;
    29.         Vector3 target = Vector3.RotateTowards(transform.forward, targetDir, angle, 0f);
    30.         transform.rotation = Quaternion.LookRotation(target);
    31.     }
    32.  
    33.     void MovmentInTwoPoints()
    34.     {
    35.         FracTime();
    36.         transform.position = Vector3.Slerp(startRot.position, endRot.position, fracComplete );
    37.     }
    38.  
    39.     void FracTime()
    40.     {
    41.         fracComplete = ((Time.time - startTime) / moveTime);
    42.  
    43.         if(fracComplete >= 1)
    44.         {
    45.             fracComplete = 0;
    46.             startTime = Time.time;
    47.             Transform temp = endRot;
    48.             endRot = startRot;
    49.             startRot = temp;
    50.         }
    51.  
    52.     }
    53. }
     
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,756
    Camera stuff is pretty tricky... you may wish to consider using Cinemachine from the Unity Package Manager.
     
  3. StarManta

    StarManta

    Joined:
    Oct 23, 2006
    Posts:
    8,741
    If your camera's target is using physics to moved, then this is probably caused by a mismatch between update cycles. Try either updating the camera in FixedUpdate, or setting the target's rigidbody to use interpolation.
     
  4. cyudani

    cyudani

    Joined:
    Mar 25, 2021
    Posts:
    7
    the camera is the only thing that moves everything else is static
     
  5. cyudani

    cyudani

    Joined:
    Mar 25, 2021
    Posts:
    7
    thanks for the advice I thought about using Cinemachine but I didn't know if it has that function(can Cinemachine do it?) plus it's kind of simple so I thought I could do it myself...
     
  6. cyudani

    cyudani

    Joined:
    Mar 25, 2021
    Posts:
    7
    in the end, I found kind of a solution, I played a bit with the speed and I made it extremely slow which made it more precise and less visible stuttering but the disadvantage is that it cant follow in time, so I made the rotation speed faster when the speed is too fast for it to follow. not the best fix but it worked.
     
  7. alexeu

    alexeu

    Joined:
    Jan 24, 2016
    Posts:
    257
    Fixing bugs by adjusting variables values is rarely a good method...
    Try this if it corresponds to your needs.

    Code (CSharp):
    1.     void rotateToward()
    2.     {
    3.         Quaternion angle = Quaternion.LookRotation(lookAt.position - transform.position);
    4.         Quaternion _LookAt = Quaternion.RotateTowards(transform.rotation, angle, 1f);
    5.         transform.rotation = _LookAt;
    6.     }
    7.  
     
  8. cyudani

    cyudani

    Joined:
    Mar 25, 2021
    Posts:
    7

    in the time I tried your code I came up with an idea which simplified my code, and it works!!!!

    Code (CSharp):
    1.     void rotateToward()
    2.     {
    3.         Vector3 targetDir = lookAt.position - transform.position;
    4.         float angle = Time.deltaTime * 360;
    5.         Vector3 target = Vector3.RotateTowards(transform.forward, targetDir, angle, 0f);
    6.         transform.rotation = Quaternion.LookRotation(target);
    7.     }
    this is the original code that I made using also unity documentation, and after seeing your code i thought wait why not remove the angle and target to use only the lookRotation and use the targetDir?

    so I did it and it worked! thank you all very much!
     
  9. alexeu

    alexeu

    Joined:
    Jan 24, 2016
    Posts:
    257
    You right. this
    Code (CSharp):
    1. Quaternion _LookAt = Quaternion.RotateTowards(transform.rotation, angle, 1f);
    is totally unuseful here. (copy / drop...) i use it insteed of LookAt() to prevent the snap between 2 target when switching between them...
    So the code could be simply

    Code (CSharp):
    1. using UnityEngine;
    2.  
    3. public class CameraScript1 : MonoBehaviour
    4. {
    5.     public Transform lookAt, startRot, endRot;
    6.     public float moveTime = 30f;
    7.     float startTime, fracComplete;
    8.  
    9.     void Start()
    10.     {
    11.         startTime = Time.time;
    12.     }
    13.  
    14.     void LateUpdate()
    15.     {
    16.         MovmentInTwoPoints();
    17.         rotateToward();
    18.     }
    19.     void MovmentInTwoPoints()
    20.     {
    21.         FracTime();
    22.         transform.position = Vector3.Slerp(startRot.position, endRot.position, fracComplete);
    23.     }
    24.     void FracTime()
    25.     {
    26.         fracComplete = (Time.time - startTime) / moveTime;
    27.  
    28.         if (fracComplete >= 1)
    29.         {
    30.             fracComplete = 0;
    31.             startTime = Time.time;
    32.             Transform temp = endRot;
    33.             endRot = startRot;
    34.             startRot = temp;
    35.         }
    36.     }
    37.     void rotateToward()
    38.     {
    39.         Quaternion angle = Quaternion.LookRotation(lookAt.position - transform.position);
    40.         transform.rotation = angle;
    41.     }
    42. }
    43.  
     
  10. alexeu

    alexeu

    Joined:
    Jan 24, 2016
    Posts:
    257
    Or simply use LookAt(lookAt) without any other quaternion...
    its a cosmetic question. with LookAt when you start the game, you have a litle snap and look directly to to target.
    With the 2 lines above (39/40) the snap is less and you look directly to target.
    With this line
    Code (CSharp):
    1. Quaternion _LookAt = Quaternion.RotateTowards(transform.rotation, angle, 1f);
    you have a smooth lookat to target Before starting to run between start & end positions. I like the kinda Dolly effect that it gives...
     
    Last edited: Jan 8, 2022