C# 如何确定360°;相对方向的角度?

C# 如何确定360°;相对方向的角度?,c#,math,angle,direction,C#,Math,Angle,Direction,我在屏幕上有一个小地图,在确定目标相对于相机的角度时遇到了问题 以下是我的一些示意图,其中包括一些相机位置和方向的示例: 黑色三角形代表相机 黑色箭头定义了它们的前进方向 蓝色箭头是从相机指向目标(=中间的红点)的方向 特定摄影机中的圆圈定义其红点的所需方向 以下是我目前的代码: //Anchored position around minimap circle void CalculateScreenPos(){ Vector3 dir = transform.position

我在屏幕上有一个小地图,在确定目标相对于相机的角度时遇到了问题

以下是我的一些示意图,其中包括一些相机位置和方向的示例:

  • 黑色三角形代表相机
  • 黑色箭头定义了它们的前进方向
  • 蓝色箭头是从相机指向目标(=中间的红点)的方向
  • 特定摄影机中的圆圈定义其红点的所需方向
以下是我目前的代码:

//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°+凸轮欧拉角.x至360°-凸轮欧拉角.x

因此,当摄像机从不看地面或天空时,它就工作了

如何通过不在角度上再次减去/添加x-eulerAngles来消除不需要的添加x-eulerAngles

angle -= cam.transform.eulerAngles.x
是一个错误的选择,因为当Angle360的结果为360时,它会再次被减分,立即导致错误的角度


圆也可以是椭球体,这就是为什么我将
eX
eY
放在所需的位置,以确定椭圆的延伸。

我不知道您使用的是什么数据类型,例如
cam.position
cam.heading
,等等。但是一些通用指南可以帮助您调试此问题

  • 编写一个单元测试。准备一些屏蔽数据,用于输入(例如设置
    凸轮位置/cam.航向
    变换
    ,等等)和输出(预期角度)。在少数情况下这样做,例如,您展示的所有六个示例。这样可以更容易地重复测试,并了解哪种情况不起作用-您可能会看到一种模式。它还使通过调试器运行代码变得容易

  • 将您的功能分解为逻辑工作单元。
    Angle360
    做什么?我想你知道它应该做什么,但我认为它实际上有两个功能

  • 获取两个矢量之间的角度(当前方向和目标方向)
  • 旋转贴图(或类似的东西)
  • 为那些断开的函数编写测试。您只是在使用一些库角度差函数-它的行为是否符合您的预期

  • 命名变量。你有一个向量叫做
    right
    -那是什么?无可奉告。它是右的,还是左的对立面的?为什么是
    Vector3.Angle(向右,向右)
    ,为什么不是
    Vector3.Angle(向右)

  • 通常情况下,由于代码不清晰、事物名称不明确以及方法不明确,您会执行一些数学运算并被绊倒。把问题分解成小块,问题就会变得明显。

    我解决了它:

    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

    去掉所有向量中的z坐标,然后只需调用
    Vector2.Angle
    即可获得角度。地图是世界的x-y投影,因此它不应取决于相机或对象的高度。我使用的世界是基于3d的,因此我使用笛卡尔坐标系,x为左/右,y为高度,z为前后。感谢您的建议,感谢您的帮助!