首页 > 解决方案 > ARTrackedImage 仅在第一次切换

问题描述

这是使用 ARFoundation 检测图像并根据设备正在扫描的图像启用对象的代码

[SerializeField]
public GameObject[] placeablePrefabs;

private Dictionary<string, GameObject> spawnedPrefabs = new Dictionary<string, GameObject>();
private ARTrackedImageManager trackedImageManager;
private JSONObject warnings;

public void Awake()
{
    trackedImageManager = GetComponent<ARTrackedImageManager>();

    foreach(GameObject prefab in placeablePrefabs)
    {
        GameObject newPrefab = Instantiate(prefab, Vector3.zero, Quaternion.identity);
        newPrefab.name = prefab.name;
        spawnedPrefabs.Add(prefab.name, newPrefab);
    }
}

private void OnEnable()
{
    trackedImageManager.trackedImagesChanged += ImageChanged;
}
private void OnDisable()
{
    trackedImageManager.trackedImagesChanged -= ImageChanged;
}
private void ImageChanged(ARTrackedImagesChangedEventArgs eventArgs)
{
    foreach(ARTrackedImage trackedImage in eventArgs.added)
    {
        UpdateImage(trackedImage);
    }
    foreach (ARTrackedImage trackedImage in eventArgs.updated)
    {
        UpdateImage(trackedImage);
    }
    foreach (ARTrackedImage trackedImage in eventArgs.removed)
    {
        spawnedPrefabs[trackedImage.name].SetActive(false);
    }
}

private void UpdateImage(ARTrackedImage trackedImage)
{
    string  name = trackedImage.referenceImage.name;
    Vector3 position = trackedImage.transform.position;

    GameObject prefab = spawnedPrefabs[name];
    prefab.transform.position = position;
    prefab.SetActive(true);

    foreach(GameObject go in spawnedPrefabs.Values)
    {
        if(go.name != name)
        {
            go.SetActive(false);
        }
    }
}

当我从一个图像切换到另一个图像时,它按预期工作,但是,如果我切换回来,没有任何反应,对象将不会再次切换可见状态。他们只在第一个 Switch上做。

标签: c#imageunity3daugmented-realityarcore

解决方案


问题是eventArgs.removed没有被调用。不知道为什么。

我使用 3.1.3 ARFoundation 和 ARCore 版本。

无论如何,我设法找到了解决方案。我会发布整个代码,以防有人想要整个想法。

它是这样的:

using System.Collections.Generic;
using UnityEngine;
using UnityEngine.XR.ARFoundation;
using System;
using UnityEngine.UI;
using UnityEngine.XR.ARSubsystems;

public class ImageRecognitionExample : MonoBehaviour
{
    private ARTrackedImageManager m_ImageManager;

    [SerializeField]
    private GameObject welcomePanel;

    [SerializeField]
    private Button dismissButton;

    [SerializeField]
    private Text imageTrackedText;

    [SerializeField]
    private GameObject[] arObjectsToPlace;

    [SerializeField]
    private Vector3 scaleFactor = new Vector3(0.1f, 0.1f, 0.1f);

    private ARTrackedImageManager m_TrackedImageManager;

    private Dictionary<string, GameObject> arObjects = new Dictionary<string, GameObject>();

    String currentActiveQR;


    void Awake()
    {
        dismissButton.onClick.AddListener(Dismiss);
        m_ImageManager = GetComponent<ARTrackedImageManager>();

        foreach (GameObject arObject in arObjectsToPlace)
        {
            GameObject newARObject = Instantiate(arObject, Vector3.zero, Quaternion.identity);
            newARObject.name = arObject.name;
            arObjects.Add(arObject.name, newARObject);
        }
    }


    void OnEnable()
    {
        m_ImageManager.trackedImagesChanged += OnTrackedImagesChanged;
    }

    void OnDisable()
    {
        m_ImageManager.trackedImagesChanged -= OnTrackedImagesChanged;
    }
    void OnTrackedImagesChanged(ARTrackedImagesChangedEventArgs eventArgs)
    {
        foreach (ARTrackedImage trackedImage in eventArgs.added)
        {
            currentActiveQR = trackedImage.referenceImage.name;
            UpdateARImage(trackedImage, currentActiveQR);
        }

        foreach (ARTrackedImage trackedImage in eventArgs.updated)
        {
            if (trackedImage.trackingState == TrackingState.Tracking)
            {
                currentActiveQR = trackedImage.referenceImage.name;
                imageTrackedText.text = currentActiveQR;
                AssignGameObject(currentActiveQR, trackedImage.transform.position);
            }
            else
            {
                if (currentActiveQR != trackedImage.referenceImage.name)
                {
                    ReAssignGameObject(trackedImage.referenceImage.name, trackedImage.transform.position);
                }
            }
        }
    }
    private void UpdateARImage(ARTrackedImage trackedImage, String name)
    {
        imageTrackedText.text = trackedImage.referenceImage.name;
        AssignGameObject(name, trackedImage.transform.position);

    }

    void AssignGameObject(string name, Vector3 newPosition)
    {
        if (arObjectsToPlace != null)
        {
            GameObject goARObject = arObjects[name];
            goARObject.SetActive(true);
            goARObject.transform.position = newPosition;
            goARObject.transform.localScale = scaleFactor;
            foreach (GameObject go in arObjects.Values)
            {
                //Debug.Log($"Go in arObjects.Values: {go.name}");
                if (go.name != name)
                {
                    go.SetActive(false);
                }
            }
        }
    }
    void ReAssignGameObject(string name, Vector3 newPosition)
    {
        if (arObjectsToPlace != null)
        {
            GameObject goARObject = arObjects[name];
            goARObject.SetActive(true);
            goARObject.transform.position = newPosition;
            goARObject.transform.localScale = scaleFactor;
            foreach (GameObject go in arObjects.Values)
            {
                if (go.name == name)
                {
                    go.SetActive(false);
                }
            }
        }
    }
    private void Dismiss() => welcomePanel.SetActive(false);

}

推荐阅读