Как разместить кнопку пользовательского интерфейса на целевом изображении с помощью AR Camera и Vuforia - PullRequest
0 голосов
/ 10 января 2019

Я хочу разместить кнопку пользовательского интерфейса в зависимости от цели изображения. Я использую движок Vuforia, и у меня есть изображение, на котором есть стулья и столы. Поэтому я хочу разместить кнопку в пользовательском интерфейсе (не виртуальную кнопку) на основе изображения. Например, одна кнопка должна быть на стуле. Когда я двигаюсь, кнопка должна переустанавливаться, чтобы всегда отображаться над стулом, а при нажатии она должна отображать 3d-текст, говорящий, что это стул. Я новичок в AR и хотел изучить некоторые из таких уроков.

1 Ответ

0 голосов
/ 10 января 2019

Вы можете разместить элементы пользовательского интерфейса в трехмерном пространстве, выбрав WorldSpace для RenderMode a Canvas (также см. Руководство ) через инспектора.

Чем вы можете просто сделать это Canvas GameObject дочерним по отношению к ImageTarget. Так что всякий раз, когда ImageTarget перемещается (путем отслеживания), Canvas автоматически перемещается, не заботясь об этом.

В качестве альтернативы вы также можете перемещать и размещать объект с этим Canvas, как любой другой объект в компоненте, например

public class PlaceCanvasOnTarget : MonoBehaviour
{
    public Transform ImageTarget;
    public Canvas CanvasToPlace;

    // set an offset for the canvas e.g. 20cm above
    public Vector3 offset = new Vector3(0, 0.2, 0);

    private void LateUpdate()
    {
        Canvas.transform.position = ImageTarget.transform.position + offset;
    }
}

Кроме того, по умолчанию дочерние элементы ImageTarget получают , а не , все они отключены onTrackingLost и включены onTrackingFound. Только некоторые компоненты отключены, но вы можете изменить это, скопировав содержимое DefaultTrackableEventHandler в пользовательский и настроить его примерно так (для вас важно только OnTrackingFound и OnTrackingLost внизу)

using UnityEngine;

namespace Vuforia
{
    /// <summary>
    /// A custom handler that implements the ITrackableEventHandler interface.
    /// </summary>
    public class DefaultTrackableEventHandler : MonoBehaviour,
    ITrackableEventHandler
    {
        #region PRIVATE_MEMBER_VARIABLES

        private TrackableBehaviour mTrackableBehaviour;

        #endregion // PRIVATE_MEMBER_VARIABLES


        #region UNTIY_MONOBEHAVIOUR_METHODS

        void Start()
        {
            mTrackableBehaviour = GetComponent<TrackableBehaviour>();
            if (mTrackableBehaviour)
            {
                mTrackableBehaviour.RegisterTrackableEventHandler(this);
            }
        }

        #endregion // UNTIY_MONOBEHAVIOUR_METHODS


        #region PUBLIC_METHODS
        public GameObject show;
        public GameObject hide;
        /// <summary>
        /// Implementation of the ITrackableEventHandler function called when the
        /// tracking state changes.
        /// </summary>
        public void OnTrackableStateChanged(
            TrackableBehaviour.Status previousStatus,
            TrackableBehaviour.Status newStatus)
        {
            if (newStatus == TrackableBehaviour.Status.DETECTED ||
                newStatus == TrackableBehaviour.Status.TRACKED ||
                newStatus == TrackableBehaviour.Status.EXTENDED_TRACKED)
            {
                OnTrackingFound();
            }
            else
            {
                OnTrackingLost();
            }
        }

        #endregion // PUBLIC_METHODS


        #region PRIVATE_METHODS

        private void OnTrackingFound()
        {
            show.SetActive(true);

            // enabled all children
            foreach(Transform child in transform)
            {
                child.gameObject.SetActive(true);
            }

            Debug.Log("Trackable " + mTrackableBehaviour.TrackableName + " found");
        }

        private void OnTrackingLost()
        {
            hide.SetActive(true);

            // disable all children
            foreach(Transform child in transform)
            {
                child.gameObject.SetActive(false);
            }

            Debug.Log("Trackable " + mTrackableBehaviour.TrackableName + " lost");
        }

        #endregion // PRIVATE_METHODS
    }
}

Для кнопки, показывающей и скрывающей некоторый текст:

  1. Добавьте Button как ребенка к Canvas.

  2. Добавьте Panel как ребенка к Canvas. И добавьте Text как ребенка к этому Panel. (Вам не нужно использовать Panel - это просто Image компонент - но может быть легче читать текст, если он помещен на полупрозрачную или непрозрачную поверхность вместо того, чтобы просто «плавать» в воздухе)

  3. Чем сделать простой компонент

    public TogglePanel : MonoBehaviour
    {
        public void Toggle()
        {
            gameObject.SetActive(!gameObject.activeSelf);
        }
    }
    
  4. Присоедините этот компонент к объекту Panel

  5. В событии Button onClick теперь ссылаются на компонент TogglePanel и выбирают метод TogglePanel -> Toggle()


Результат должен быть теперь

  • OnTracking потерян: Canvas (кнопка и панель с текстом) исчезают

  • OnTracking найдено: Canvas (кнопка и панель evtl с текстом) появляется и всегда должен быть на вершине стула (imageTarget);

  • OnButtonClick: Панель с текстом должна быть включена или отключена

...