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