效果如下:
代码如下:
public class TPSCamera : MonoBehaviour { /// <summary> /// 目标对象 /// </summary> [SerializeField] Transform target = null; /// <summary> /// 旋转参数 /// </summary> [SerializeField] Vector2 rotate; /// <summary> /// 旋转速度 /// </summary> [SerializeField] float rotateSpeed = 2; /// <summary> /// 视口大小 /// </summary> [SerializeField] float viewSize = 30; /// <summary> /// 默认角度 /// 在目标对象的哪个方向 /// </summary> [SerializeField] float defaultAngle = -135; /// <summary> /// 离目标对象的距离 /// </summary> [SerializeField] float radius = 3; /// <summary> /// 离目标对象的高度 /// </summary> [SerializeField] float height = 1.5f; public bool Aim; public bool visiable = false; public CursorLockMode lockMode; Camera cam; /// <summary> /// 绕任意轴旋转的参考点 /// 暂时用这个办法替代 /// </summary> Transform tr; static TPSCamera _inst; public static TPSCamera inst { get { return _inst; } } void Awake () { _inst = this; } void Start () { cam = this.GetComponent<Camera> (); tr = new GameObject ().transform; } void FixedUpdate () { rotate.x += Input.GetAxis ("Mouse X") * rotateSpeed; rotate.y += Input.GetAxis ("Mouse Y") * rotateSpeed; viewSize -= Input.mouseScrollDelta.y * 3; //一些约束,不用管 if (viewSize < 30) { viewSize = 30; } else if (viewSize > 60) { viewSize = 60; } if (rotate.y < -60) { rotate.y = -60; } else if (rotate.y > 45) { rotate.y = 45; } cam.fieldOfView = viewSize; Cursor.visible = visiable; Cursor.lockState = lockMode; } void LateUpdate () { Transform self = this.transform; Vector3 targetPos = target.position; targetPos.y += height; //旋转y轴,左右滑动 Vector2 v1 = IMath.CalcAbsolutePoint (rotate.x, radius); self.position = targetPos + new Vector3 (v1.x, 0, v1.y); //相机的观察点 Vector2 v2 = IMath.CalcAbsolutePoint (rotate.x + defaultAngle, radius); Vector3 viewPoint = new Vector3 (v2.x, 0, v2.y) + targetPos; //计算2点之间的距离 float dist = Vector3.Distance (self.position, viewPoint); //取中点作为旋转轴 Vector3 center = Vector3.MoveTowards (self.position, viewPoint, dist / 2); //这里我不知道怎么计算这个任意轴,暂时先用这个方法替代 tr.position = center; tr.LookAt (targetPos); tr.eulerAngles += new Vector3 (0, 0, rotate.y); //旋转x轴,上下滑动 Vector3 temp = tr.right * dist / 2; self.position = tr.position - temp; self.LookAt (tr.position + temp); } }
public static Vector2 CalcAbsolutePoint (float angle, float dist) { angle += 90; dist = -dist; float x = dist * Mathf.Cos (-angle * Mathf.PI / 180); float y = dist * Mathf.Sin (-angle * Mathf.PI / 180); return new Vector2 (x, y); }