Problem solved. Here is the working script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CameraScript : MonoBehaviour {
public GameObject target;
public Transform cameraPosition;
[HideInInspector] public Orientation angle;
public float sensitivity = 1;
public float minDistance = 0.75f;
float distance;
private Rigidbody mRigidbody;
void Start () {
distance = Vector3.Distance (transform.position, target.transform.position + Vector3.up * 1.75f);
angle = new Orientation((target.transform.position + Vector3.up * 1.75f) - transform.position);
mRigidbody = target.GetComponent<Rigidbody> ();
}
void FixedUpdate () {
float x = Input.GetAxis ("Mouse X") * sensitivity;
float y = Input.GetAxis ("Mouse Y") * sensitivity;
float z = Input.GetAxis ("Mouse ScrollWheel") * sensitivity;
angle.Add (x, y);
if (angle.v > 70) {
angle.v = 70;
} else if (angle.v < -70) {
angle.v = -70;
}
distance += z;
if (distance <= minDistance) {
distance = minDistance;
transform.position = cameraPosition.position;
mRigidbody.MoveRotation (angle.HorizontalRotation());
} else {
transform.position = target.transform.position + Vector3.up * 1.75f - angle.ToVector3 () * distance;
}
transform.rotation = angle.Rotation();
}
}
public struct Orientation{
public float h; //horizontal
public float v; //vertical
public Orientation(Vector3 vect){
vect.Normalize ();
v = Mathf.Asin (vect.y) * 180 / Mathf.PI;
vect.y = 0;
vect.Normalize ();
if (vect.z < 0) {
h = 180 - Mathf.Asin (vect.x) * 180 / Mathf.PI;
} else {
h = Mathf.Asin (vect.x) * 180 / Mathf.PI;
}
}
public void Add(float x, float y){
h = (h + x) % 360;
v = (v + y) % 360;
}
public static Orientation Sum(Orientation or1, Orientation or2){
Orientation or = or1;
or.h = (or.h + or2.h) % 360;
or.v = (or.v + or2.v) % 360;
return or;
}
public Vector3 ToVector3(){
Vector3 vect = Vector3.zero;
vect.x = Mathf.Sin (h * Mathf.PI / 180) * Mathf.Cos (v * Mathf.PI / 180);
vect.y = Mathf.Sin (v * Mathf.PI / 180);
vect.z = Mathf.Cos (h * Mathf.PI / 180) * Mathf.Cos (v * Mathf.PI / 180);
return vect;
}
public Quaternion Rotation(){
Vector3 vect = Vector3.zero;
vect.x = Mathf.Sin (h * Mathf.PI / 180) * Mathf.Cos (v * Mathf.PI / 180);
vect.y = Mathf.Sin (v * Mathf.PI / 180);
vect.z = Mathf.Cos (h * Mathf.PI / 180) * Mathf.Cos (v * Mathf.PI / 180);
return Quaternion.LookRotation (vect);
}
public Quaternion HorizontalRotation(){
Vector3 vect = Vector3.zero;
vect.x = Mathf.Sin (h * Mathf.PI / 180);
vect.z = Mathf.Cos (h * Mathf.PI / 180);
return Quaternion.LookRotation (vect);
}
public Quaternion VerticalRotation(){
Vector3 vect = Vector3.zero;
vect.y = Mathf.Sin (v * Mathf.PI / 180);
vect.z = Mathf.Cos (v * Mathf.PI / 180);
return Quaternion.LookRotation (vect);
}
public static Orientation forward {
get{
return new Orientation ();
}
}
public static Orientation back {
get{
return new Orientation (Vector3.back);
}
}
public static Orientation up {
get {
return new Orientation (Vector3.up);
}
}
public static Orientation down {
get{
return new Orientation (Vector3.down);
}
}
public static Orientation left {
get {
return new Orientation (Vector3.left);
}
}
public static Orientation right {
get{
return new Orientation (Vector3.right);
}
}
public static bool operator == (Orientation or1, Orientation or2){
return or1.Equals (or2);
}
public static bool operator != (Orientation or1, Orientation or2){
return !or1.Equals (or2);
}
}
I also fixed some errors in the calculations, and added a bit more methods.