ok, so i’ve fixed the jitter issue, but when i went to change my character this morning from a capsule to a cube, for some reason, my character started flying up into the air? here’s the current code :
using UnityEngine;
using System.Collections;
public class CameraController : MonoBehaviour {
[ Header ( "Target Properties" ) ]
public Transform target;
public LayerMask collisionLayers = -1;
[ Header ( "camera Properties" ) ]
public bool invertX = false;
public bool invertY = false;
public float targetHeight = 1.7f;
public float distance = 5.0f;
public float offsetFromWall = 0.1f;
public float minDistance = 0.6f;
public float maxDistance = 20.0f;
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 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 float smoothTime = 0.01f; // The `time` it takes for the `camera` to `smoothly` `rotate`
// to its' new rotation
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 yMinPitch = -180.0f; // The `minimum` allowed range in which to rotate the camera
// on the `Y` axis
public float yMaxPitch = 180.0f; // The `maximum` allowed range in which to rotate the camera
// on the `Y` axis
public float damper = 5.0f; //
public int zoomRate = 40;
public float rotationDampening = 3.0f;
public float zoomDampening = 5.0f;
private float xDeg = 0.0f;
private float yDeg = 0.0f;
private float currentDistance;
private float desiredDistance;
private float correctedDistance;
private Vector3 vTargetOffset;
private bool isMenuOpen = false;
private static readonly float PanSpeed = 20.0f;
private static readonly float ZoomSpeedTouch = 0.1f;
// private static readonly float ZoomSpeedMouse = 0.5f;
private static readonly float[] BoundsX = new float[] { -10.0f, 5.0f };
private static readonly float[] BoundsZ = new float[] { -18.0f, -4.0f };
private static readonly float[] ZoomBounds = new float[] { 10.0f, 85.0f };
private Camera cam;
private Vector3 lastPanPosition;
private int panFingerId; // Touch mode ONLY
private bool wasZoomingLastFrame; // Touch mode ONLY
private Vector2[] lastZoomPositions; // Touch mode ONLY
void Awake ( ) {
cam = GetComponent <Camera> ( );
}
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;
}
}
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, minDistance, maxDistance );
correctedDistance = desiredDistance;
// Calculate desired camera position from `mouse wheel`
vTargetOffset = new Vector3 ( 0, -targetHeight, 0 );
}
// Camera logic on LateUpdate to only update after all character movement logic
// has been handled
void Update ( ) {
// Don't do anything if `target` is `not defined`
if ( ! target ) { return; }
// Don't do anything if `menu` is `open`
if ( isMenuOpen ) { return; }
// If `Touch` is indeed supported & app is `NOT` running as
// `WebGL` `App`
if ( Input.touchSupported && Application.platform != RuntimePlatform.WebGLPlayer ) {
// Switch to `Touch` Control{s}
// HandleTouch ( );
}
// Otherwise,
else {
// Switch to `Mouse` Control{s}
// HandleMouse ( );
}
// If either mouse buttons are down, let the mouse
// take over camera position
if ( Input.GetMouseButton ( 0 ) ) {
xDeg += Input.GetAxis("Mouse Y") * sensitivityX * ( invertX ? -1 : 1 );
yDeg += Input.GetAxis("Mouse X") * sensitivityY * ( invertY ? -1 : 1 );
// Clamp X-Angle to prevent `camera` `flipping`
xDeg = ClampAngle ( xDeg, xMinPitch, xMaxPitch );
}
// 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 ( );
Vector3 position = target.position - ( rotation * Vector3.forward * desiredDistance + vTargetOffset );
// 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, minDistance, maxDistance );
// Recalculate position based on the new currentDistance
position = target.position - ( rotation * Vector3.forward * currentDistance + vTargetOffset );
// Spherically `Linear` `Interpolate` the `rotation`'s
// `Quaternion`
/*
transform.rotation = Quaternion.Slerp (
transform.rotation, rotation,
damper
);
*/
// Set the `position`'s transform to the `recalculated`
// `position`
transform.position = position;
transform.rotation = rotation;
// Set `camera` to look at the
// `target`
// transform.LookAt ( target );
}
// Allows for `angle` to be `clamped`
private static float ClampAngle ( float angle, float min, float max ) {
// Prevent `angle` from being `clamped` past negative `360.0`
// degrees
// Prevent `angle` from being `clamped` past positive `360.0`
// degrees
if ( angle < -360.0f ) { angle += 360.0f; }
if ( angle > 360.0f ) { angle -= 360.0f; }
// Return the newly `clamped` `angle
return Mathf.Clamp ( angle, min, max );
}
// Allows for `Panning` of `camera`
private void PanCamera ( Vector3 newPanPosition ) {
// Determine how much to move the camera
Vector3 offset = cam.ScreenToViewportPoint ( lastPanPosition - newPanPosition );
Vector3 move = new Vector3 (
offset.x * PanSpeed, 0, offset.y * PanSpeed
);
// Perform the movement
transform.Translate ( move, Space.World );
// Set the `Vector3` `pos` to the Position values, { `X`, `Y`, `Z` }
Vector3 pos = transform.position;
// Ensure the camera remains within bounds
pos.x = Mathf.Clamp ( transform.position.x, BoundsX [ 0 ], BoundsX [ 1 ] );
pos.z = Mathf.Clamp ( transform.position.z, BoundsZ [ 0 ], BoundsZ [ 1 ] );
// Set the Position values, { `X`, `Z` } to newly `Clamped`
// value{s}
transform.position = pos;
// Cache the position
lastPanPosition = newPanPosition;
}
// Allows `camera`'s `fieldOfView` to `Zoom` in or out, given an
// `offset` | { A `Zoom` `level` } & `speed`
private void ZoomCamera ( float offset, float speed ) {
if ( offset == 0 ) { return; }
cam.fieldOfView = Mathf.Clamp (
cam.fieldOfView - ( offset * speed ),
ZoomBounds [ 0 ],
ZoomBounds [ 1 ]
);
}
// Handles `Touch` Controls
private void HandleTouch ( ) {
switch ( Input.touchCount ) {
// Panning
case 1 :
wasZoomingLastFrame = false;
// If the touch began, capture its position and its finger ID
// Otherwise, if the finger ID of the touch doesn't match,
// skip it
Touch touch = Input.GetTouch ( 0 );
if ( touch.phase == TouchPhase.Began ) {
lastPanPosition = touch.position;
panFingerId = touch.fingerId;
} else if ( touch.fingerId == panFingerId && touch.phase == TouchPhase.Moved ) {
PanCamera ( touch.position );
}
break;
case 2 : // Zooming
Vector2[] newPositions = new Vector2[] {
Input.GetTouch ( 0 ).position,
Input.GetTouch ( 1 ).position
};
if ( ! wasZoomingLastFrame ) {
lastZoomPositions = newPositions;
wasZoomingLastFrame = true;
}
else {
// Zoom based on the distance between the new positions compared
// to the distance between the previous positions
float newDistance = Vector2.Distance (
newPositions [ 0 ],
newPositions [ 1 ]
);
float oldDistance = Vector2.Distance (
lastZoomPositions [ 0 ],
lastZoomPositions [ 1 ]
);
float offset = newDistance - oldDistance;
ZoomCamera ( offset, ZoomSpeedTouch );
lastZoomPositions = newPositions;
}
break;
default :
wasZoomingLastFrame = false;
break;
}
}
// Handles `Mouse` Controls
private void HandleMouse ( ) {
// On mouse down, capture its' position
// Otherwise, if the mouse is still down,
// pan the camera
if ( Input.GetMouseButtonDown ( 1 ) ) {
lastPanPosition = Input.mousePosition;
} else if ( Input.GetMouseButton ( 1 ) ) {
PanCamera ( Input.mousePosition );
}
// Check for scrolling to zoom the camera
// float scroll = Input.GetAxis ( "Mouse ScrollWheel" );
// ZoomCamera ( scroll, ZoomSpeedMouse );
}
}