Как сделать двухмерную стрелку на экране, которая всегда указывает на 3d-объект внутри сцены AR - PullRequest
0 голосов
/ 30 апреля 2019

Я хочу отобразить 2D-стрелку на экране, которая всегда перемещается, чтобы указывать на 3D-объект в сцене AR.

Вопрос заключается в том, как измерить угол, на который должна повернуться стрелка.укажите нужный 3D-объект.
Заранее спасибо.

Ответы [ 4 ]

1 голос
/ 30 апреля 2019

Одна из стратегий - спроецировать положение вашего объекта на экранное пространство.Затем вычислите вектор между положением вашей стрелки и этим спроецированным положением.Вы можете использовать этот вектор для вычисления угла поворота, например, от вертикального направления, используя Dot Product, за которым следует 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))
  • Вы используете холст в режиме рендеринга: пространство экрана- Наложение.Приведенный выше код был бы другим, если бы Canvas находился в World Space.
1 голос
/ 30 апреля 2019

Как обзор высокого уровня:

  • Найти направление от центра пользовательского интерфейса / плоскости обзора к трехмерному объекту
  • Проецируйте направление на пользовательский интерфейс / плоскость обзора (используя вперед как вектор нормали) и нормализуйте
  • Направить 2D-стрелку в направлении проекции
0 голосов
/ 30 апреля 2019

Спасибо всем, ребята, я получил ответ на две ситуации: Первый: когда два объекта находятся в 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);
    }
0 голосов
/ 30 апреля 2019

Используйте встроенную * Unity Transform.LookAt функцию

...