Unity中摄像机围绕物体旋转的功能

当然啦其实围绕旋转的功能本身并不难:
        // 拖动摄像机围绕物体旋转
        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;

猜你喜欢

转载自blog.csdn.net/qq_34444468/article/details/80528370