Unity ARFoundation, problem with creating Canvas with multiple image tracking

114 Views Asked by At

Everything is working correctly, unless that i'm only able to see the canvas to each image once. Is there some way to reset this UpdateTrackedImages method when I enter the DisableMe() function? Tryed to set trackedImage to null but it didn't work... The canvas is the same to all of them, but the button will receive different information. And I should be able to come back to every one of them.

private void UpdateTrackedImages(IEnumerable<ARTrackedImage> trackedImages)
    {
        // If the same image (ReferenceImageName)
        foreach (var trackedImage in trackedImages)
        {
            if (Chairs.Contains(trackedImage.referenceImage.name))
            {
                if (trackedImage.trackingState == TrackingState.Tracking)
                {
                    Invoke("EnableMe", 0.5f);
                }

                if (trackedImage.trackingState != TrackingState.Tracking)
                {
                    Invoke("DisableMe", 0.5f);
                }
            }
        }
    }

    private void EnableMe()
    {
        canvas.enabled = true;
    }
    private void DisableMe()
    {
        canvas.enabled = false;
        trackedImage = null;
    }

I've tried to set trackedImage to null but it didn't work... The canvas is the same to all of them, but the button will receive different information. And I should be able to come back to every one of them.

2

There are 2 best solutions below

2
On

It seems there is a need to reset the state of the tracked images when you enter the DisableMe() function, so you can see the canvas for each image again.

The issue you are facing is because the trackedImage variable is declared inside the foreach loop and is not accessible outside of it. Therefore, when you call trackedImage = null; inside the DisableMe() function, it only affects the local variable inside that function, not the ones in the foreach loop.

To resolve this, you can declare a class-level variable for trackedImage that will store the currently tracked image. Here's the modified code to achieve that:


    private ARTrackedImage currentTrackedImage; // Declare a class-level variable to store the current tracked image

private void UpdateTrackedImages(IEnumerable<ARTrackedImage> trackedImages)
{
    // If the same image (ReferenceImageName)
    foreach (var trackedImage in trackedImages)
    {
        if (Chairs.Contains(trackedImage.referenceImage.name))
        {
            if (trackedImage.trackingState == TrackingState.Tracking)
            {
                currentTrackedImage = trackedImage; // Store the currently tracked image
                Invoke("EnableMe", 0.5f);
            }

            if (trackedImage.trackingState != TrackingState.Tracking)
            {
                Invoke("DisableMe", 0.5f);
            }
        }
    }
}

private void EnableMe()
{
    canvas.enabled = true;
}

private void DisableMe()
{
    canvas.enabled = false;
    currentTrackedImage = null; // Reset the currently tracked image when disabling the canvas
}

Now, by using the currentTrackedImage variable, you should be able to enable and disable the canvas for each tracked image independently. Remember to also check if currentTrackedImage is not null before accessing it in other parts of your code.

0
On

Problem solved!

I've created a dictionary instead of a list, now I can create and destroy the canvas more than once. I've put also a text inside the canvas, for testing pourpose. Here is the complete fixed code. I think that it can be also done for instantiating game objects, but the repositoning tatic is working for my well by now. Basically hiding the prefab from the player when not being used.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Linq;
using UnityEngine.Events;
using UnityEngine.XR.ARFoundation;
using UnityEngine.XR.ARSubsystems;
using Unity.VisualScripting;
using System.Runtime.CompilerServices;
using UnityEngine.SceneManagement;
using UnityEditor;
using UnityEngine.UI;

public class CanvasOn2 : MonoBehaviour
{
    public Behaviour Canvas;
    public Text nome;

    Canvas canvas;

    private void Start()
    {
        canvas = gameObject.GetComponent<Canvas>();
        canvas.enabled = false;
        nome.text = string.Empty;
    }

    public List<string> ListOfObjects = new List<string>();
    private ARTrackedImageManager _TrackedImageManager;



    private void Awake()
    {
        _TrackedImageManager = FindObjectOfType<ARTrackedImageManager>();
    }
    private void OnEnable()
    {
        if (_TrackedImageManager != null)
        {
            _TrackedImageManager.trackedImagesChanged += OnTrackedImagesChanged;
        }
    }
    private void OnDisable()
    {
        if (_TrackedImageManager != null)
        {
            _TrackedImageManager.trackedImagesChanged -= OnTrackedImagesChanged;
        }
    }
    private void OnTrackedImagesChanged(ARTrackedImagesChangedEventArgs e)
    {
        foreach (var trackedImage in e.added)
        {
            Debug.Log($"Tracked image detected: {trackedImage.referenceImage.name} with size: {trackedImage.size}");
        }
        UpdateTrackedImages(e.added);
        UpdateTrackedImages(e.updated);
    }

    private Dictionary<string, TrackingState> trackedImageStates = new Dictionary<string, TrackingState>();

    public void UpdateTrackedImages(IEnumerable<ARTrackedImage> trackedImages)
    {
        foreach (var trackedImage in trackedImages)
        {
            string imageName = trackedImage.referenceImage.name;

            if (ListOfObjects.Contains(imageName))
            {
                if (!trackedImageStates.ContainsKey(imageName))
                {
                    trackedImageStates.Add(imageName, TrackingState.None);
                }

                if (trackedImage.trackingState != trackedImageStates[imageName])
                {
                    trackedImageStates[imageName] = trackedImage.trackingState;

                    if (trackedImage.trackingState == TrackingState.Tracking)
                    {
                        nome.text = trackedImage.referenceImage.name;
                        Invoke("EnableMe", 0.5f);
                    }
                    else
                    {
                        Invoke("DisableMe", 0.5f);
                    }
                }
            }
        }
    }
    private void EnableMe()
    {
        canvas.enabled = true;
    }
    private void DisableMe()
    {
        canvas.enabled = false;
    }
}