Camera Jitters When Displacing and Rotating Smoothly
I tried to make a simple Third Person Camera that displaces and rotates towards a given target, with the following key parameters:
- Following types for both displacement and rotation. Right now the enum is just { Instant, Smooth }. 
- Axes to ignore for both displacement and rotation, all axes in an enum. 
- Axes to invert for the orbiting functionality. 
- 'Relative Following' for both displacement and rotation. If the flags are checked the displacement/rotation will be relative to the target's orientation ('target.rotation displacement' and 'target.rotation rotation' for displacement and rotation respectively). 
- An offset vector, which is affected by the displacement relative following's flag. It is treated as a normalized vector at runtime. 
- A scalar of the aforementioned offset. Which is basically de distance between the camera and the target. 
- An offset vector as Euler for the rotation, it is equally affected by the rotation relative following's flag. 
- Other attributes, such as 'displacementFollowDuration', 'maxDisplacementFollowSpeed', 'rotationFollowDuration', 'maxRotationFollowingSpeed', etc., are for the smooth following. The attributes not mentioned are either self-explanatory or irrelevant (at least that's what I want to think, correct me if I may be wrong). 
The Problem:
When the smooth flags are enabled for both displacement and rotation, the camera starts to shake, I think it has something to do with the rotation.
Things I've tried already:
- Call the rotation and displacement following on different threads (being Update, Late Update and FixedUpdate), not yet on coroutines. This time I made an enum 'LoopType' to encapsulate all threads, and avoid re-compiling each time I move the functions. 
- Use different kinds of time deltas. By the same fashion of the threads, I made an enum 'TimeDelta' which encapsulates the 3 types of time deltas Unity offers. 
- Change the smooth functions for both displacement and rotation, such as Lerp, SmoothDamp, Slerp, even custom elastic functions, etc. 
- Sacrifing 1 frame by following the target's point of the last frame, as proposed here: https://answers.unity.com/questions/1351106/jittery-movement-of-the-camera-when-rotating-and-m-1.html. 
- Given that the target's displacement is that of a Rigidbody, this post ( https://answers.unity.com/questions/1201551/when-applying-custom-camera-smoothness-camera-shak-1.html ) suggests to attach a Rigidbody to the camera and displace/rotate it by Rigidbody.position/Rigidbody.rotation respectively. 
Camera's Script:
 using System;
 using System.Collections;
 using System.Collections.Generic;
 using UnityEngine;
 #if UNITY_EDITOR
 using UnityEditor;
 #endif
 
 [Flags]
 public enum Axes
 {
     None = 0,
     X = 1,
     Y = 2,
     Z = 4,
 
     XAndY = X | Y,
     XAndZ = X | Z,
     YAndZ = Y | Z,
     All = X | Y | Z
 }
 
 public enum LoopType { Update, LateUpdate, FixedUpdate }
 
 public enum TimeDelta { Default, Fixed, Smooth }
 
 public enum FollowingType { Instant, Smooth }
 
 /// \TODO Maybe something like Lucky Tale and Resident Evil 4 and 5 camera (return to the original rotation if there are no axes)
 [RequireComponent(typeof(Rigidbody))]
 public class GameplayCamera : MonoBehaviour
 {
     public Transform target;                         /// Camera's Target.
     [Space(5f)]
     [Header("Displacement Following's Attributes:")]
     public LoopType followDisplacementAt;             /// Loop to do the Displacement Following.
     public FollowingType displacementFollowType;     /// Type of Following for Displacement.
     public TimeDelta displacementTimeDelta;         /// Displacement's Time Delta.
     public Axes ignoreDisplacementAxes;             /// Displacement Axes to Ignore.
     public Axes invertAxes;                         /// Axes to Invert.
     public Axes limitOrbitAxes;                     /// Orbit's Axes to Limit.
     public bool relativeDisplacementFollow;         /// Follow Target's Displacement Relative to Target's Orientation?.
     public bool limitDisplacementFollow;             /// Limit Displacement Following's Speed?.
     public Vector3 displacementOffset;                 /// [Normalized] Displacement Offset between Camera and Target.
     public Vector2 orbitSpeed;                         /// Orbit's Speed on each Axis.
     public Vector2 minOrbitLimits;                     /// Orbit's Negative Boundaries.
     public Vector2 maxOrbitLimits;                     /// Orbit's Positive Boundaries.
     public float displacementFollowDuration;         /// Displacement's Follow Duration.
     public float maxDisplacementFolowSpeed;         /// Maximum Displacement's Follow Duration.
     public float minDistance;                         /// Minimum Distance Between Camera and Target.
     public float maxDistance;                         /// Maximum Distance Between Camera and Target.
     [Space(5f)]
     [Header("Rotation Following's Attributes:")]
     public LoopType followRotationAt;                 /// Loop to do the Rotation Following.
     public FollowingType rotationFollowType;         /// Type of Following for Rotation.
     public TimeDelta rotationTimeDelta;             /// Rotations' Time Delta.
     public Axes ignoreRotationAxes;                 /// Rotation Axes to Ignore.
     public bool relativeRotationFollow;             /// Follow Target's Rotation Relative to Target's Orientation?.
     public bool limitRotationFollow;                 /// Limit Rotation Following's Speed?.
     public Vector3 eulerRotationOffset;             /// Rotation Offset between Camera and Target as Euler.
     public float rotationFollowDuration;             /// Rotation's Following Duration.
     public float maxRotationFollowSpeed;             /// Maximum Rotation's Following Speed.
     [Space(5f)]
     public Vector3 up;                                 /// Up Vector's Reference.
     [HideInInspector] public Vector3 forward;         /// Reoriented Forward's Vector.
     private Vector3 eulerOrbitRotation;             /// Current Orbit Rotation as Euler.
     private Vector3 displacementVelocity;             /// Displacement's Velocity.
     private Quaternion orbitRotation;                 /// Orbit Rotation as Quaternion.
     private Quaternion rotationOffset;                 /// Rotation's Offset as Quaternion.
     private Vector2 inputAxes;                         /// Input's Axes.
     private float currentDistance;                     /// Current Distance from Camera and Player.
     private float angularSpeed;                     /// Angular's Speed.
     private Rigidbody _rigidbody;                     /// Rigidbody's Component.
 
     /// <summary>Gets rigidbody Component.</summary>
     public Rigidbody rigidbody
     { 
         get
         {
             if(_rigidbody == null) _rigidbody = GetComponent<Rigidbody>();
             return _rigidbody;
         }
     }
 
 #region UnityMethods:
     /// <summary>Draws Gizmos on Editor mode.</summary>
     private void OnDrawGizmos()
     {
         Gizmos.color = Color.green;
         Gizmos.DrawRay(rigidbody.position, up);
         Gizmos.color = Color.blue;
         Gizmos.DrawRay(rigidbody.position, forward);
 
         if(target != null)
         {
             Gizmos.color = Color.cyan;
             Gizmos.DrawLine(target.position, GetOffsetPoint());
 
             if(!Application.isPlaying)
             {
                 UpdateRotationOffset();
                 ReorientForward();
             }
 
             Quaternion rotation = rigidbody.rotation * rotationOffset;
 
             Handles.color = new Color(1.0f, 0.0f, 0.0f, 0.35f); /// Red
             Handles.DrawSolidArc(rigidbody.position, transform.right, transform.forward, Vector3.Angle(transform.forward, rotation * Vector3.forward) * Mathf.Sign(eulerRotationOffset.x), 1.0f);
             Handles.color = new Color(0.0f, 1.0f, 0.0f, 0.35f); /// Green
             Handles.DrawSolidArc(rigidbody.position, transform.up, transform.right, Vector3.Angle(transform.right, rotation * Vector3.right) * Mathf.Sign(eulerRotationOffset.y), 1.0f);
             Handles.color = new Color(1.0f, 0.0f, 1.0f, 0.35f); /// Blue
             Handles.DrawSolidArc(rigidbody.position, transform.forward, transform.up, Vector3.Angle(transform.up, rotation * Vector3.up) * Mathf.Sign(eulerRotationOffset.z), 1.0f);
         
             if(!Application.isPlaying)
             {
                 rigidbody.position = GetOffsetPoint();
                 rigidbody.rotation = Quaternion.LookRotation(GetLookDirection()) * rotationOffset;
             }
         }        
     }
 
     /// <summary>Resets GameplayCamera's instance to its default values.</summary>
     private void Reset()
     {
         up = Vector3.up;
     }
 
     /// <summary>GameplayCamera's instance initialization when loaded [Before scene loads].</summary>
     private void Awake()
     {
         rigidbody.isKinematic = true;
     }
     
     /// <summary>GameplayCamera's tick at each frame.</summary>
     private void Update()
     {
         if(target == null) return;
 
         TrackInput();
         UpdateRotationOffset();
 
         if(followDisplacementAt == LoopType.Update) DisplacementFollow();
         if(followRotationAt == LoopType.Update) RotationFollow();
     }
     
     /// <summary>Updates GameplayCamera's instance at the end of each frame.</summary>
     private void LateUpdate()
     {
         if(target == null) return;
 
         if(followDisplacementAt == LoopType.LateUpdate) DisplacementFollow();
         if(followRotationAt == LoopType.LateUpdate) RotationFollow();
 
         ReorientForward();
     }
 
     /// <summary>Updates GameplayCamera's instance at each Physics Thread's frame.</summary>
     private void FixedUpdate()
     {
         if(target == null) return;
 
         if(followDisplacementAt == LoopType.FixedUpdate) DisplacementFollow();
         if(followRotationAt == LoopType.FixedUpdate) RotationFollow();
     }
 #endregion
 
     /// <summary>Tracks Input.</summary>
     private void TrackInput()
     {
         inputAxes.x = Input.GetAxis("Mouse Y");
         inputAxes.y = Input.GetAxis("Mouse X");
     }
 
     /// <summary>Performs the Displacement's Following.</summary>
     private void DisplacementFollow()
     {
         if(inputAxes.sqrMagnitude > 0.0f) OrbitInAxes(inputAxes.x, inputAxes.y);
 
         switch(displacementFollowType)
         {
             case FollowingType.Instant:
             rigidbody.position = GetOffsetPoint();
             break;
 
             case FollowingType.Smooth:
             rigidbody.position = GetSmoothDisplacementFollowDirection();
             break;
         }
     }
 
     /// <summary>Performs the Rotation's Following.</summary>
     private void RotationFollow()
     {
         switch(rotationFollowType)
         {
             case FollowingType.Instant:
             rigidbody.rotation = Quaternion.LookRotation(GetLookDirection()) * rotationOffset;
             break;
 
             case FollowingType.Smooth:
             rigidbody.rotation = GetSmoothFollowRotation();
             break;
         }
     }
 
     /// <summary>Orbits Camera in Given Axes.</summary>
     /// <param name="x">X's Axis.</param>
     /// <param name="y">Y's Axis.</param>
     private void OrbitInAxes(float x, float y)
     {
         if((invertAxes | Axes.X) == invertAxes) x *= -1.0f;
         if((invertAxes | Axes.Y) == invertAxes) y *= -1.0f;
 
         float xRotation = (x * orbitSpeed.x * GetTimeDelta(displacementTimeDelta));
         float yRotation = (y * orbitSpeed.y * GetTimeDelta(displacementTimeDelta));
 
         eulerOrbitRotation.x = (limitOrbitAxes | Axes.X) == limitOrbitAxes ?
             Mathf.Clamp(eulerOrbitRotation.x + xRotation, minOrbitLimits.x, maxOrbitLimits.x) : eulerOrbitRotation.x + xRotation;
         eulerOrbitRotation.y = (limitOrbitAxes | Axes.Y) == limitOrbitAxes ?
             Mathf.Clamp(eulerOrbitRotation.y + yRotation, minOrbitLimits.y, maxOrbitLimits.y) : eulerOrbitRotation.y + yRotation;
 
         orbitRotation = Quaternion.Euler(eulerOrbitRotation);
     }
 
     /// <returns>Gets the smooth displacement following's Vector.</returns>
     private Vector3 GetSmoothDisplacementFollowDirection()
     {
         return Vector3.SmoothDamp
         (
             rigidbody.position,
             GetOffsetPoint(),
             ref displacementVelocity,
             displacementFollowDuration,
             limitDisplacementFollow ? maxDisplacementFolowSpeed : Mathf.Infinity,
             GetTimeDelta(displacementTimeDelta)
         );
     }
 
     /// <summary>Gets Offset Point, with the Orbit's Rotation already combined.</summary>
     private Vector3 GetOffsetPoint()
     {
         Vector3 scaledOffset = displacementOffset.normalized * maxDistance;
         Vector3 point = target.position + (orbitRotation * (relativeDisplacementFollow ? target.rotation * scaledOffset : scaledOffset));
         
         if((ignoreDisplacementAxes | Axes.X) == ignoreDisplacementAxes) point.x = rigidbody.position.x;
         if((ignoreDisplacementAxes | Axes.Y) == ignoreDisplacementAxes) point.y = rigidbody.position.y;
 
         return point;
     }
 
     /// <returns>Looking Direction, taking into account the axes to ignore.</returns>
     private Vector3 GetLookDirection()
     {
         Vector3 direction = target.position - rigidbody.position;
 
         if((ignoreRotationAxes | Axes.X) == ignoreRotationAxes) direction.x = rigidbody.position.x;
         if((ignoreRotationAxes | Axes.Y) == ignoreRotationAxes) direction.y = rigidbody.position.y;
         if((ignoreRotationAxes | Axes.Z) == ignoreRotationAxes) direction.z = rigidbody.position.z;
 
         return direction;
     }
 
     /// <return>Following Rotation, with the Rotation's Offset already combined.</return>
     private Quaternion GetSmoothFollowRotation()
     {
         Quaternion rotation = Quaternion.LookRotation(GetLookDirection()) * rotationOffset;
         float angle = Quaternion.Angle(rigidbody.rotation, rotation);
 
         if(angle > 0.0f)
         {
             float t = Mathf.SmoothDampAngle(
                 angle,
                 0.0f,
                 ref angularSpeed,
                 rotationFollowDuration,
                 limitRotationFollow ? maxRotationFollowSpeed : Mathf.Infinity,
                 GetTimeDelta(rotationTimeDelta)
             );
             return Quaternion.Slerp(rigidbody.rotation, rotation, t);
         }
 
         return rotation;
     }
 
     /// <summary>Updates the Rotation's Offset Given the Wuler Representation.</summary>
     private void UpdateRotationOffset()
     {
         Quaternion rotation = Quaternion.Euler(eulerRotationOffset);
         rotationOffset = relativeRotationFollow ? target.rotation * rotation : rotation;
     }
 
     /// <summary>Reorients Forward's Vector.</summary>
     private void ReorientForward()
     {
         forward = Vector3.Cross(transform.right, up);
     }
 
     /// <summary>Gets Time's Delta.</summary>
     /// <param name="_pa">Time Delta's Type.</param>
     /// <returns>Time's Delta of the Given Type.</returns>
     private float GetTimeDelta(TimeDelta _timeDelta = TimeDelta.Default)
     {
         switch(_timeDelta)
         {
             case TimeDelta.Default: return Time.deltaTime;
             case TimeDelta.Fixed:     return Time.fixedDeltaTime;
             case TimeDelta.Smooth:     return Time.smoothDeltaTime;
             default:                 return 0.0f;
         }
     }
 }
  
I also made a quick Character's script for the sake of giving a quick example (the original Character script I have a has tons of dependencies). So its jump does not have cooldown, and it doesn't evaluate if it is grounded.
Simple Character Movement's Script:
 using System;
 using System.Collections;
 using System.Collections.Generic;
 using UnityEngine;
 
 [RequireComponent(typeof(Rigidbody))]
 public class CharacterMovement : MonoBehaviour
 {
     [SerializeField] private GameplayCamera camera;     /// Gameplay's Camera.
     [Space(5f)]
     [SerializeField] private KeyCode jumpKey;             /// Jump's KeyCode.
     [SerializeField] private KeyCode displacementKey;     /// Displacement's Key.
     [SerializeField] private float displacementSpeed;     /// Displacements Speed.
     [SerializeField] private float jumpForce;             /// Jump's Force .
     [SerializeField] private ForceMode mode;             /// Jump Force' sMode.
     private Rigidbody rigidbody;                         /// Rigidbody's Component.
 
 #region UnityMethods:
     /// <summary>CharacterMovement's instance initialization.</summary>
     private void Awake()
     {
         rigidbody = GetComponent<Rigidbody>();
     }
     
     /// <summary>CharacterMovement's tick at each frame.</summary>
     private void Update ()
     {
         Vector3 axes = new Vector3
         (
             Input.GetAxis("Horizontal"),
             0.0f,
             Input.GetAxis("Vertical")
         );
 
         if(axes.sqrMagnitude > 0.0f)
         {
             transform.rotation = Quaternion.LookRotation(axes);
             transform.Translate(transform.forward * displacementSpeed * Time.deltaTime, Space.World);
         }
         if(Input.GetKeyDown(jumpKey)) Jump();
     }
 #endregion
 
     /// <summary>Performs Jump.</summary>
     private void Jump()
     {
         rigidbody.AddForce(Vector3.up * jumpForce, mode);
     }
 }
   
What I Want to Know:
If I am missing something, I am using the wrong functions, calling the functions in the wrong threads/orders, etc. Please let me know if there is more information I have to provide.
Your answer
 
 
              koobas.hobune.stream
koobas.hobune.stream 
                       
                
                       
			     
			 
                