Unity中摄像机的重要性毋庸置疑,关于摄像机的操作也有很多,比如第一人称跟随,第二人称跟随,摄像机的拉近拉远等等,下面就暂时实现摄像机的拉近拉远和旋转:
创建新的场景,场景中添加一个cube,然后给cube添加新的脚本,脚本内容如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 using UnityEngine; using System.Collections; public class TestCube : MonoBehaviour { private GameObject rotateObj; private GameObject camera; public float speed = 3f; private bool rotate = false ; public float maxView = 90; public float minView = 10; void Start() { rotateObj = GameObject.Find( "Rotate" ); camera = GameObject.Find( "Main Camera" ); } void Update () { //滑动鼠标滑轮控制视角的大小 float offsetView = Input.GetAxis( "Mouse ScrollWheel" ) * speed; float tmpView = offsetView + Camera.main.fieldOfView; tmpView = Mathf.Clamp(tmpView, minView, maxView); Camera.main.fieldOfView = tmpView; //绕主角旋转摄像机 if (rotate) { camera.transform.RotateAround(transform.position, Vector3.up, speed * Input.GetAxis( "Mouse X" )); } if (Input.GetMouseButtonDown(0)) { rotate = true ; } if (Input.GetMouseButtonUp(0)) { rotate = false ; } } } 当然啦其实围绕旋转的功能本身并不难: // 拖动摄像机围绕物体旋转 if (Input.GetMouseButton(1)) { x += Input.GetAxis("Mouse X") * speed * Time.deltaTime; y += Input.GetAxis("Mouse Y") * speed * Time.deltaTime; Quaternion q = Quaternion.Euler(y, x, 0); Vector3 direction = q * Vector3.forward; this.transform.position = center - direction * distance; this.transform.LookAt(center); } 用代码把摄像机移动到指定位置也不难: public void MoveTo(Vector3 vecCenter, Vector3 vecPosition, float time) { // 设置缺省中心点 center = vecCenter; defaultCenter = vecCenter; defaultPositon = vecPosition; distance = Vector3.Distance(defaultCenter, defaultPositon); // 移动位置(用了DOTween做平滑) Sequence seq = DOTween.Sequence(); seq.Append(this.transform.DOMove(vecPosition, time).SetEase(Ease.Linear)); seq.Play().OnUpdate(delegate { this.transform.LookAt(vecCenter); }); } 困难的是,用代码移动之后,用户再用鼠标控制摄像机时,会出现视角跳跃的现象。 这个问题的核心在于,MoveTo() 的时候没有设置适当的 x 与 y 值,所以解决方案本来很简单,只要把这两个值设置一下就行了。 但是! 四元数的乘法是没有逆运算的! 也就是说,下面这一句求direction的代码不能逆运算: Vector3 direction = q * Vector3.forward; 当然其实办法还是有的,就像这样: Quaternion.FromToRotation(Vector3.forward, direction); 但算出来的 q 和原来的 q 长得不一样…… 为什么说“长得不一样”呢?因为这两个四元数本质上是等价的(但不要问我为什么,我的数学是体育老师教的…… 而且我还发现,q 和下面这个四元数对于【求direction的代码】也是等价的: Quaternion.Euler(q.eulerAngles.x, q.eulerAngles.y, 0); 于是问题就这样解决了,在 MoveTo() 中给 x 和 y 这样赋值: // 计算 x,y 的值 distance = Vector3.Distance(vecCenter, vecPosition); Vector3 direction = (vecCenter - vecPosition) / distance; Quaternion q2 = Quaternion.FromToRotation(Vector3.forward, direction); x = q2.eulerAngles.y; y = q2.eulerAngles.x;