Unity中摄像机绕物体旋转和拉近拉远视角的操作

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;
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值