Weird Rotation?

So I’m trying to stop this from rotating strangly sometimes. What am I doing wrong here? : Here is the full code :

using UnityEngine;
using System.Collections;
using AppUtils;

public class CameraController : MonoBehaviour {

   public Transform target;
   public float targetHeight = 1.7f;

   public LayerMask collisionLayers = -1;
   public float offsetFromWall = 0.1f;

   public float sensitivityX = 10.0f;              // The `X` `speed` `sensitivity` of the `mouse` in which the camera
                                                   // rotates in units

   public float sensitivityY = 8.0f;               // The `Y` `speed` `sensitivity` of the `mouse` in which the camera
                                                   // rotates in units

   public bool invertXRotation = false;
   public bool invertYRotation = false;

   public int switchRotationMode = 1;              // Which camera rotation mode to use
                                                   // Defaults to mode `1`
                                                   // Mode `0` :: { Looks `up` when moving `mouse` `down`... }
                                                   // Mode `1` :: { Looks `down` when moving `mouse` `up`... }

   public float xVelocity = 200.0f;                // The `X` `speed` in which the camera rotates in units
   public float yVelocity = 200.0f;                // The `Y` `speed` in which the camera rotates in units

   public float distance = 5.0f;

   public float zoomMindistance = 5.0f;
   public float zoomMaxdistance = 20.0f;

   public float xMinPitch = -80.0f;                // The `minimum` allowed range in which to rotate the camera
                                                   // on the `X` axis

   public float xMaxPitch = 80.0f;                 // The `maximum` allowed range in which to rotate the camera
                                                   // on the `X` axis

   public float yMinYaw = -180.0f;                 // The `minimum` allowed range in which to rotate the camera
                                                   // on the `Y` axis

   public float yMaxYaw = 180.0f;                  // The `maximum` allowed range in which to rotate the camera
                                                   // on the `Y` axis

   public float zoomRate = 40.0f;
   public float zoomDampening = 5.0f;

   public float smoothTime = 0.01f;                // The `time` it takes for the `camera` to `smoothly` `rotate`
                                                   // to its' new rotation

   public float rotationDampening = 3.0f;

   public float damper = 5.0f;                     // The `minimum` allowed `damper` for
                                                   // `smoothing` camera speed

   private float xDeg = 0.0f;
   private float yDeg = 0.0f;

   private float currentDistance;
   private float desiredDistance;
   private float correctedDistance;

   private float startRotationX = 0.0f;            // Default `X` rotation when mouse button is
                                                   // not held

   private float startRotationY = 0.0f;            // Default `Y` rotation when mouse button is
                                                   // not held

   private Vector3 vTargetOffset;

   private void CalculateZoom ( ) {

       // Calculate the desired distance for `mouse wheel`

       desiredDistance -= Input.GetAxis ( "Mouse ScrollWheel" ) * Time.deltaTime * zoomRate * Mathf.Abs ( desiredDistance );
       desiredDistance = Mathf.Clamp ( desiredDistance, zoomMindistance, zoomMaxdistance );
       correctedDistance = desiredDistance;

       // Calculate desired camera position from `mouse wheel`

       vTargetOffset = new Vector3 ( 0, -targetHeight, 0 );

   }

   private void Awake ( ) {

       cam = GetComponent <Camera> ( );

   }

   private void Start ( ) {

       Vector3 angles = transform.eulerAngles;
       xDeg = angles.x;
       yDeg = angles.y;

       currentDistance = distance;
       desiredDistance = distance;
       correctedDistance = distance;

       // Make the rigid body not change rotation

       if ( GetComponent <Rigidbody> ( ) ) {

           GetComponent <Rigidbody> ( ).freezeRotation = true;

       }

       startRotationX = 0.0f;
       startRotationY = 0.0f;

   }

   private void Update ( ) {

       if ( Input.GetMouseButton ( 0 ) ) {

           xDeg += Input.GetAxis("Mouse Y") * sensitivityX * ( invertXRotation ? -1 : 1 );
           yDeg += Input.GetAxis("Mouse X") * sensitivityY * ( invertYRotation ? -1 : 1 );

           // Clamp X-Angle to prevent `camera` `flipping`

           xDeg = ClampAngle ( xDeg, xMinPitch, xMaxPitch );

       }

       if ( Input.GetMouseButtonUp ( 0 ) ) {

           xDeg = startRotationX;
           yDeg = startRotationY;

       }

       // Set camera rotation

       // Quaternion rotation = Quaternion.Euler ( xDeg, yDeg, 0 );

       Quaternion rotation = Quaternion.Slerp(
           transform.rotation, Quaternion.Euler(xDeg, yDeg, 0),
           damper * Time.deltaTime
       );

       // Calculate `Zoom` for `camera`

       CalculateZoom ( );

       if ( target != null ) {

           Vector3 position = target.position - ( rotation * Vector3.forward * desiredDistance + vTargetOffset );
           var oldPosition = position;

           // Check for collision using the true target's desired registration
           // point as set by user using height

           RaycastHit collisionHit;

           Vector3 trueTargetPosition = new Vector3 ( target.position.x,  target.position.y + targetHeight, target.position.z );

           // If there was a collision, correct the camera position & calculate
           // the corrected distance

           bool isCorrected = false;

           if ( Physics.Linecast ( trueTargetPosition, position, out collisionHit, collisionLayers.value ) ) {

               // Calculate the distance from the original estimated
               // position to the collision location,
               // subtracting out a safety "offset" distance from the
               // object we hit
               // The offset will help keep the camera from being
               // right on top of the surface we hit,
               // which usually shows up as the
               // surface geometry getting
               // partially clipped by the camera's front
               // clipping plane

               correctedDistance = Vector3.Distance ( trueTargetPosition, collisionHit.point ) - offsetFromWall;
               isCorrected = true;

           }

           // For smoothing, lerp distance only if either distance wasn't
           // corrected, or correctedDistance is
           // more than currentDistance

           currentDistance = ! isCorrected || correctedDistance > currentDistance ? Mathf.Lerp ( currentDistance, correctedDistance, Time.deltaTime * zoomDampening ) : correctedDistance;

           // Keep within standard limits

           currentDistance = Mathf.Clamp ( currentDistance, zoomMindistance, zoomMaxdistance );

           // Recalculate position based on the new currentDistance

           position = target.position - ( rotation * Vector3.forward * currentDistance + vTargetOffset );

           // Set the `position`'s transform to the `recalculated`
           // `position`

           transform.position = position;

           // Set the `rotation`'s transform to the `recalculated`
           // `rotation`

           transform.rotation = rotation;

       }

   }

}

The line{s} I’m looking at are : 112, 113 & 119 - 144

Here are the videos of the camera rotating correctly as well as incorrectly :

The 1st video is correct rotation
The 2nd video is incorrect rotation

vrj9zi
fk18kr

Any help is GREATLY appreciated!

Thanks & have a great day!

I don’t understand what’s different about the behavior in the second video - the behavior looks very similar to me. What’s the problem?

@StarManta : There’s what appears to be, Z-Rotation.

nshqou

That probably comes from your Quaternion.Slerp. Quaternions are interesting in that sometimes an X rotation + Y rotation can cause an apparent Z rotation to happen, and that’s especially true if you do some additional math on them, like Slerp.

Try replacing Quaternion.Slerp with Lerping your own xDeg/yDeg values prior to putting them into a Quaternion at all, maybe?

Slerp is going to rotate on all your Axes. You could 0 out the Z after the slerp, but that will very likely give you other weird rotations you don’t want.

@StarManta : How do I do that in this code?