如何从相对方向确定 360° 角?
How to determine an 360° angle from relative direction?
我在屏幕上有一个小地图,但无法确定目标相对于相机的角度。
这里是我的意思的一些图,以及一些相机位置和方向的例子:
- 黑色三角形代表相机。
- 黑色箭头定义了它们的前进方向。
- 蓝色箭头是从相机到目标(= 中间的红点)的方向。
- 特定相机中的圆圈定义了其红点的所需方向。
到目前为止,这是我的代码:
//Anchored position around minimap circle
void CalculateScreenPos(){
Vector3 dir = transform.position - cam.position; //xz distance
dir.y = 0;
angle = Angle360(cam.forward.normalized, dir.normalized, cam.right);
Vector2 desiredPosition = new Vector2(
eX * -Mathf.Cos(angle * Mathf.PI/180f) * dir.z,
eY * Mathf.Sin(angle * Mathf.PI/180f) * dir.x
);
minimapBlip.anchoredPosition = desiredPosition;
}
public static float Angle360(Vector3 from, Vector3 to, Vector3 right)
{
float angle = Vector3.Angle(from, to);
return (Vector3.Angle(right, to) > 90f) ? 360f - angle : angle;
}
但是角度好像不太对,发现范围是
0° + cam.eulerXAngles.x to 360° - cam.eulerAngles.x
所以当摄像头从不看向地面或天空时,它会起作用。
如何通过不再 substracting/adding 将不需要的添加 x-eulerAngles 删除到角度?
angle -= cam.transform.eulerAngles.x
是一个糟糕的选择,因为当 Angle360 的结果为 360 时,它会再次被减去,立即导致错误的角度。
圆也可以是椭圆,这就是为什么我将 eX
和 eY
放在确定椭圆延伸的所需位置。
我不知道您使用的是什么数据类型,例如cam.position
、cam.heading
等,但一些一般指导可帮助您调试此问题。
编写单元测试。准备一些固定数据,用于输入(例如设置 cam.position/cam.heading
、transform
等)和输出(预期角度)。在某些情况下执行此操作,例如您展示的所有六个示例。这样可以更轻松地重复您的测试,并了解哪种情况不起作用 - 您可能会看到一个模式。它还使通过调试器 运行 您的代码变得容易。
将您的功能分解为逻辑工作单元。 Angle360
是做什么的?我想你明白它应该做什么,但我认为它实际上是两个功能
- 获取两个向量(当前方向和目标方向)的夹角
- 旋转地图(或类似的东西)
为那些被分解的函数编写测试。您只是在使用一些库角度差函数 - 它的行为是否符合您的预期?
命名你的变量。您有一个名为 right
的矢量 - 那是什么?没有评论。它是 right
中的 'correct' 还是 'opposite of left' 中的?为什么是Vector3.Angle(right, to)
,为什么不是Vector3.Angle(to, right)
?
通常,您在执行一些数学运算时会被绊倒,因为您的代码不清晰、事物命名不正确以及方法不清晰。将问题分解成更小的部分,问题就会变得很明显。
我解决了:
angle = Mathf.Atan2(heading.x, heading.z) * Mathf.Rad2Deg-Camera.main.transform.eulerAngles.y;
Vector2 desiredPosition = new Vector2(
eX * -Mathf.Cos((angle+90) * Mathf.Deg2Rad),
eY * Mathf.Sin((angle+90) * Mathf.Deg2Rad)
);
感谢您到目前为止的帮助,祝您编码愉快 :D
我在屏幕上有一个小地图,但无法确定目标相对于相机的角度。
这里是我的意思的一些图,以及一些相机位置和方向的例子:
- 黑色三角形代表相机。
- 黑色箭头定义了它们的前进方向。
- 蓝色箭头是从相机到目标(= 中间的红点)的方向。
- 特定相机中的圆圈定义了其红点的所需方向。
到目前为止,这是我的代码:
//Anchored position around minimap circle
void CalculateScreenPos(){
Vector3 dir = transform.position - cam.position; //xz distance
dir.y = 0;
angle = Angle360(cam.forward.normalized, dir.normalized, cam.right);
Vector2 desiredPosition = new Vector2(
eX * -Mathf.Cos(angle * Mathf.PI/180f) * dir.z,
eY * Mathf.Sin(angle * Mathf.PI/180f) * dir.x
);
minimapBlip.anchoredPosition = desiredPosition;
}
public static float Angle360(Vector3 from, Vector3 to, Vector3 right)
{
float angle = Vector3.Angle(from, to);
return (Vector3.Angle(right, to) > 90f) ? 360f - angle : angle;
}
但是角度好像不太对,发现范围是
0° + cam.eulerXAngles.x to 360° - cam.eulerAngles.x
所以当摄像头从不看向地面或天空时,它会起作用。
如何通过不再 substracting/adding 将不需要的添加 x-eulerAngles 删除到角度?
angle -= cam.transform.eulerAngles.x
是一个糟糕的选择,因为当 Angle360 的结果为 360 时,它会再次被减去,立即导致错误的角度。
圆也可以是椭圆,这就是为什么我将 eX
和 eY
放在确定椭圆延伸的所需位置。
我不知道您使用的是什么数据类型,例如cam.position
、cam.heading
等,但一些一般指导可帮助您调试此问题。
编写单元测试。准备一些固定数据,用于输入(例如设置
cam.position/cam.heading
、transform
等)和输出(预期角度)。在某些情况下执行此操作,例如您展示的所有六个示例。这样可以更轻松地重复您的测试,并了解哪种情况不起作用 - 您可能会看到一个模式。它还使通过调试器 运行 您的代码变得容易。将您的功能分解为逻辑工作单元。
Angle360
是做什么的?我想你明白它应该做什么,但我认为它实际上是两个功能- 获取两个向量(当前方向和目标方向)的夹角
- 旋转地图(或类似的东西)
为那些被分解的函数编写测试。您只是在使用一些库角度差函数 - 它的行为是否符合您的预期?
命名你的变量。您有一个名为
right
的矢量 - 那是什么?没有评论。它是right
中的 'correct' 还是 'opposite of left' 中的?为什么是Vector3.Angle(right, to)
,为什么不是Vector3.Angle(to, right)
?
通常,您在执行一些数学运算时会被绊倒,因为您的代码不清晰、事物命名不正确以及方法不清晰。将问题分解成更小的部分,问题就会变得很明显。
我解决了:
angle = Mathf.Atan2(heading.x, heading.z) * Mathf.Rad2Deg-Camera.main.transform.eulerAngles.y;
Vector2 desiredPosition = new Vector2(
eX * -Mathf.Cos((angle+90) * Mathf.Deg2Rad),
eY * Mathf.Sin((angle+90) * Mathf.Deg2Rad)
);
感谢您到目前为止的帮助,祝您编码愉快 :D