在 Unity 中查找忽略 origin.forward 的 2 点之间的角度

Find angle between 2 points ignoring origin.forward in Unity

背景:我正在开发一款AR寻宝应用。很简单,它有一个定位器,可以告诉您宝藏相对于您的位置。我在 AR 世界中以相机为原点,以宝物为对象。

问题:我想根据space宝藏所在的位置旋转我的箭头。但在 2d 中。基本上,我会忽略 camera.forward.

的相对前向平面

例子:如果默认相机旋转,角度可以计算为atan2(dy,dx)。如果相机直视下方,则角度为 atan2(dz,dx)。

我试过的:

Quaternion lookRot = Quaternion.LookRotation(target.transform.position - origin.transform.position);
Quaternion relativeRot = Quaternion.Inverse(origin.transform.rotation) * lookRot;

相对旋转在 3d space 中是正确的,但我想将其转换为 2d,忽略 camera.forward 平面。所以即使宝物在镜头前或镜头后,也不应该改变角度。

计算 x 和 y 坐标的差异,只需将一个对象的 transform.x 减去另一个对象的 transform.x 和 y 坐标的相同过程,然后使用 Mathf.atan(差异in y/difference in x) 来计算角度。然后将 z 旋转到这个角度并将 x 和 y 旋转分配给它们已经是的。

好的,我希望这是有道理的。您将需要某种 if 语句来确定您的角色是否沿着 x、y 或 z 平面看。希望图表清楚地说明了这些参数是什么,但如果不是的话。例如,要查看“x”平面,y 旋转必须在 45° 和 -45° 或 135° 和 -135° 之间,并且 z 旋转必须在 45° 和 -45° 之间或之间135°和-135°。

基本上,您得到的是一个分成六个部分的球体,两个部分对应角色可以观察的每个平面。一旦你确定了角色在看哪个平面,你就可以通过找到角色和宝藏之间沿着角色没有看的两个平面的位置差异来确定方向。然后用trig算出角度

事实证明,有一种非常简单的方法可以获取目标的相对 X 和 Y。

Vector2 ExtractRelativeXY(Transform origin, Transform target) {
    // Get the absolute look rotation from origin to target.
    Quaternion lookRot = Quaternion.LookRotation(target.transform.position - origin.transform.position);
    // Create a relative look rotation with respect to origin's forward.
    Quaternion relativeRot = Quaternion.Inverse(origin.transform.rotation) * lookRot;
    // Obtain Matrix 4x4 from the rotation.
    Matrix4x4 m = Matrix4x4.Rotate(relativeRot);
    // Get the 3rd column (which is the forward vector of the rotation).
    Vector4 mForward = m.GetColumn(2);
    // Simply extract the x and y.
    return new Vector2(mForward.x, mForward.y);
  }

获得 x 和 y 后,按照 MBo 和 Tom 的建议使用 angle = atan2(y,x) 将其转换为角度。

之所以可行,是因为四元数的矩阵分量可以在多个向量中演示。在这里 可以找到更好的插图。

回复一个旧帖子,但我一直在努力解决同样的问题并找到了一个相对简单的解决方案:

将目标的位置(相对于原点)投影到由相机的前向矢量定义的平面上。然后向投影点旋转:

Vector3 diff = target.transform.position - origin.transform.position;
Vector3 projected = Vector3.ProjectOnPlane(diff, Camera.main.transform.forward);
origin.transform.rotation = Quaternion.LookRotation(projected);