效果如下:

代码如下:
1public class TPSCamera : MonoBehaviour 2{ 3 /// <summary> 4 /// 目标对象 5 /// </summary> 6 [SerializeField] 7 Transform target = null; 8 9 /// <summary> 10 /// 旋转参数 11 /// </summary> 12 [SerializeField] 13 Vector2 rotate; 14 15 /// <summary> 16 /// 旋转速度 17 /// </summary> 18 [SerializeField] 19 float rotateSpeed = 2; 20 21 /// <summary> 22 /// 视口大小 23 /// </summary> 24 [SerializeField] 25 float viewSize = 30; 26 27 /// <summary> 28 /// 默认角度 29 /// 在目标对象的哪个方向 30 /// </summary> 31 [SerializeField] 32 float defaultAngle = -135; 33 34 /// <summary> 35 /// 离目标对象的距离 36 /// </summary> 37 [SerializeField] 38 float radius = 3; 39 40 /// <summary> 41 /// 离目标对象的高度 42 /// </summary> 43 [SerializeField] 44 float height = 1.5f; 45 46 public bool Aim; 47 48 public bool visiable = false; 49 50 public CursorLockMode lockMode; 51 52 Camera cam; 53 54 /// <summary> 55 /// 绕任意轴旋转的参考点 56 /// 暂时用这个办法替代 57 /// </summary> 58 Transform tr; 59 60 static TPSCamera _inst; 61 62 public static TPSCamera inst 63 { 64 get { 65 return _inst; 66 } 67 } 68 69 void Awake () 70 { 71 _inst = this; 72 } 73 74 void Start () 75 { 76 cam = this.GetComponent<Camera> (); 77 tr = new GameObject ().transform; 78 } 79 80 void FixedUpdate () 81 { 82 rotate.x += Input.GetAxis ("Mouse X") * rotateSpeed; 83 rotate.y += Input.GetAxis ("Mouse Y") * rotateSpeed; 84 viewSize -= Input.mouseScrollDelta.y * 3; 85 86 //一些约束,不用管 87 if (viewSize < 30) 88 { 89 viewSize = 30; 90 } else if (viewSize > 60) 91 { 92 viewSize = 60; 93 } 94 95 if (rotate.y < -60) 96 { 97 rotate.y = -60; 98 } else if (rotate.y > 45) 99 { 100 rotate.y = 45; 101 } 102 103 cam.fieldOfView = viewSize; 104 Cursor.visible = visiable; 105 Cursor.lockState = lockMode; 106 } 107 108 void LateUpdate () 109 { 110 Transform self = this.transform; 111 Vector3 targetPos = target.position; 112 targetPos.y += height; 113 114 //旋转y轴,左右滑动 115 Vector2 v1 = IMath.CalcAbsolutePoint (rotate.x, radius); 116 self.position = targetPos + new Vector3 (v1.x, 0, v1.y); 117 118 //相机的观察点 119 Vector2 v2 = IMath.CalcAbsolutePoint (rotate.x + defaultAngle, radius); 120 Vector3 viewPoint = new Vector3 (v2.x, 0, v2.y) + targetPos; 121 122 //计算2点之间的距离 123 float dist = Vector3.Distance (self.position, viewPoint); 124 125 //取中点作为旋转轴 126 Vector3 center = Vector3.MoveTowards (self.position, viewPoint, dist / 2); 127 128 //这里我不知道怎么计算这个任意轴,暂时先用这个方法替代 129 tr.position = center; 130 tr.LookAt (targetPos); 131 tr.eulerAngles += new Vector3 (0, 0, rotate.y); 132 133 //旋转x轴,上下滑动 134 Vector3 temp = tr.right * dist / 2; 135 self.position = tr.position - temp; 136 self.LookAt (tr.position + temp); 137 138 } 139 140} 141 142public static Vector2 CalcAbsolutePoint (float angle, float dist) 143{ 144 angle += 90; 145 dist = -dist; 146 float x = dist * Mathf.Cos (-angle * Mathf.PI / 180); 147 float y = dist * Mathf.Sin (-angle * Mathf.PI / 180); 148 return new Vector2 (x, y); 149}