如何在屏幕上制作始终指向AR场景内3d对象的2D箭头

时间:2019-04-30 14:16:25

标签: unity3d augmented-reality vuforia

我想在屏幕上显示一个2D箭头,该箭头始终移动以指向AR场景中的3D对象。

问题是如何测量箭头旋转以指向所需3D对象的角度。
预先感谢。

4 个答案:

答案 0 :(得分:1)

作为高级概述:

  • 找到从UI /视平面中心到3D对象的方向
  • 将方向投射到UI /视图平面上(使用正向作为法向矢量),并进行规范化
  • 将2D箭头指向投影方向

答案 1 :(得分:1)

一种策略是将对象的位置投影到屏幕空间中。 然后计算箭头位置和投影位置之间的向量。您可以使用该向量来计算点的旋转角度,例如,垂直方向,使用点积,后跟acos。

最后,您需要进行一点乘积计算,以确定上述旋转是顺时针还是逆时针。

以下是一些示例代码:

    public GameObject Target;

    RectTransform rt;

    void Start()
    {
        rt = GetComponent<RectTransform>();
    }

    void Update()
    {
        // Get the position of the object in screen space
        Vector3 objScreenPos = Camera.main.WorldToScreenPoint(Target.transform.position);

        // Get the directional vector between your arrow and the object
        Vector3 dir = (objScreenPos - rt.position).normalized;

        // Calculate the angle 
        // We assume the default arrow position at 0° is "up"
        float angle = Mathf.Rad2Deg * Mathf.Acos(Vector3.Dot(dir, Vector3.up));

        // Use the cross product to determine if the angle is clockwise
        // or anticlockwise
        Vector3 cross = Vector3.Cross(dir, Vector3.up);
        angle = -Mathf.Sign(cross.z) * angle;

        // Update the rotation of your arrow
        rt.localEulerAngles = new Vector3(rt.localEulerAngles.x, rt.localEulerAngles.y, angle);
    }

对于上面的代码,我认为:

  • 您仅使用一台主相机,您可能需要更改它
  • 您的箭头在画布上,默认情况下指向上方(当其旋转为(0,0,0)时)
  • 您正在“渲染”模式下使用画布:屏幕空间-覆盖。如果“画布”位于世界空间中,则上面的代码将有所不同。

答案 2 :(得分:0)

使用Unity内置的Transform.LookAt函数

答案 3 :(得分:0)

谢谢大家,我得到了两种情况的答案: 第一个:当两个对象处于3D模式时

    public GameObject flesh;
    public GameObject target;
    // Start is called before the first frame update
    void Start()
    {
        flesh.transform.position = Camera.main.ScreenToWorldPoint(new Vector3( Screen.width/2, Screen.height/2,1));
    }

    // Update is called once per frame
    void Update()
    {
        var dir = Camera.main.WorldToScreenPoint(target.transform.position) - 
        Camera.main.WorldToScreenPoint(flesh.transform.position);
        var angle = Mathf.Atan2(dir.y, dir.x) * Mathf.Rad2Deg;
        flesh.transform.rotation = Quaternion.AngleAxis(angle, Vector3.forward);
    }

第二:当肉是具有RectTransform的图像时, ,此解决方案源自@kevernicus

public GameObject Target;

    RectTransform rt;

    void Start()
    {
        rt = GetComponent<RectTransform>();
    }

    void Update()
    {
        // Get the position of the object in screen space
        Vector3 objScreenPos = Camera.main.WorldToScreenPoint(Target.transform.position);

        // Get the directional vector between your arrow and the object
        Vector3 dir = (objScreenPos - rt.position).normalized;

        float angle = Mathf.Rad2Deg * Mathf.Atan2(dir.y, dir.x);


        rt.rotation = Quaternion.AngleAxis(angle, Vector3.forward);
    }