Search Unity

  1. Are you interested in providing feedback directly to Unity teams? Sign up to become a member of Unity Pulse, our new product feedback and research community.
    Dismiss Notice
  2. Read here for Unity's latest plans on OpenXR.
    Dismiss Notice

AR Foundation - Multiple Tracked Image Managers?

Discussion in 'AR' started by drewfjacobs, Jun 19, 2019.

  1. drewfjacobs

    drewfjacobs

    Joined:
    Mar 12, 2019
    Posts:
    8
    I am trying to have different prefabs spawn for different images tracked. Would it it possible to just add a second AR Tracked Image Manager with a separate Reference Library and Tracked Image Prefab assigned to it in order to achieve this goal?
     
    mtessmann and Deleted User like this.
  2. tdmowrer

    tdmowrer

    Unity Technologies

    Joined:
    Apr 21, 2017
    Posts:
    604
    The AR managers are effectively singletons, so you should generally not use two of them. You can, however, set the active reference image library and the prefab at runtime.

    Another option to achieve this might be to use a prefab which just contains a single MonoBehaviour script that can decide which other prefab to instantiate as a child of itself.
     
    annarqi likes this.
  3. BMythes

    BMythes

    Joined:
    Feb 20, 2018
    Posts:
    6
    Sorry for reviving this thread, I'm just working on exactly the same thing you described here.

    A solution I was thinking was instantiating a Gameobject A that would be a parent of different prefabs B, C and D (all child prefabs start as inactive). And then, depending on which image is read from the library, it activates one of the prefabs.

    I also thought about having the library of images become an array, and associate that array with an array of prefabs. Hence, Image [0] would instantiate Prefab [0], etc.

    Are any of these solutions valid, and could you possibly point towards how to solve them? I'm still a beginner at code having a hard time with editing ARFoundation's code.

    Thank you!
     
    Deleted User likes this.
  4. Deleted User

    Deleted User

    Guest

    Has anyone been able to figure this one out? I tried tdmowrer approach but ended up crashing the app. Is there an example of how to do it?
     
  5. jpvanmuijen

    jpvanmuijen

    Joined:
    Aug 23, 2012
    Posts:
    11
  6. tdmowrer

    tdmowrer

    Unity Technologies

    Joined:
    Apr 21, 2017
    Posts:
    604
    In ARFoundation 3.0, it is now possible to add an ARTrackedObjectManager and then set its reference object library. This wasn't possible before because it would throw if enabled without a reference object library. From the changelog:
    What is the callstack?
     
    Deleted User likes this.
  7. Deleted User

    Deleted User

    Guest

    @tdmowrer I actually figured that an unused Wikitude library reference I was playing with was causing the crash, sorry for the confusion. I'll try the approach given by @jpvanmuijen and see how it goes, thanks!
     
  8. waldgeist

    waldgeist

    Joined:
    May 6, 2017
    Posts:
    219
    I think it's a must-have to be able to set a different prefab for each trackable image. Otherwise, this feature is pretty useless. Yes, you could do this by letting a single prefab decide what to spawn below it, but that is a quite weird workaround.

    Actually, the approach Vuforia is following here makes more sense to me: The game object is created first, and then a tracking script is used on top of that game object which references the trackable image. So each time this image is recognized, the game object will be activated and placed at the image's position.
     
    apiotuch likes this.
  9. ayagiku

    ayagiku

    Joined:
    Jan 17, 2020
    Posts:
    1
    I found TrackedImageManager has only a single prefab just now (3.0). When multiple trackers are set TrackedImageManager , the manager shows multiple same prefabs.
    Whether I looked for codes that instanciate the prefab to modify the manager into be able to handle different prefabs, couldn't find it in the class. The instanciation codes may be written in any other location which catches tracking status updated event object. Do anybodies know how to show defferent prefabs by tracked images?

    best regards.
     
  10. Markus_T

    Markus_T

    Joined:
    Jan 23, 2014
    Posts:
    8
    You can track a separate object with each tracking image using this script.
    Add this script to your AR Session Origin gameObject and make sure that the Objects To Place list has the same number of gameObjects as there are images in your Reference Image Library. For this script, the gameObjects must be in your scene.

    You should also set the Tracked Image Prefab in the AR Tracked Image Manager to None.

    Code (CSharp):
    1.  
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using UnityEngine.XR.ARFoundation;
    5. using UnityEngine.XR.ARSubsystems;
    6.  
    7. [RequireComponent(typeof(ARTrackedImageManager))]
    8. public class TrackMultiple : MonoBehaviour
    9. {
    10.     [Header("The length of this list must match the number of images in Reference Image Library")]
    11.     public List<GameObject> ObjectsToPlace;
    12.  
    13.     private int refImageCount;
    14.     private Dictionary<string, GameObject> allObjects;
    15.     private ARTrackedImageManager arTrackedImageManager;
    16.     private IReferenceImageLibrary refLibrary;
    17.  
    18.     void Awake()
    19.     {
    20.         arTrackedImageManager = GetComponent<ARTrackedImageManager>();
    21.     }
    22.  
    23.     private void OnEnable()
    24.     {
    25.         arTrackedImageManager.trackedImagesChanged += OnImageChanged;
    26.     }
    27.  
    28.     private void OnDisable()
    29.     {
    30.         arTrackedImageManager.trackedImagesChanged -= OnImageChanged;
    31.     }
    32.  
    33.     private void Start()
    34.     {
    35.         refLibrary = arTrackedImageManager.referenceLibrary;
    36.         refImageCount = refLibrary.count;
    37.         LoadObjectDictionary();
    38.     }
    39.  
    40.     void LoadObjectDictionary()
    41.     {
    42.         allObjects = new Dictionary<string, GameObject>();
    43.         for (int i = 0; i < refImageCount; i++)
    44.         {
    45.             allObjects.Add(refLibrary[i].name, ObjectsToPlace[i]);
    46.             ObjectsToPlace[i].SetActive(false);
    47.         }
    48.     }
    49.  
    50.     void ActivateTrackedObject(string _imageName)
    51.     {
    52.         allObjects[_imageName].SetActive(true);
    53.     }
    54.  
    55.     public void OnImageChanged(ARTrackedImagesChangedEventArgs _args)
    56.     {
    57.         foreach (var addedImage in _args.added)
    58.         {
    59.             ActivateTrackedObject(addedImage.referenceImage.name);
    60.         }
    61.  
    62.         foreach (var updated in _args.updated)
    63.         {
    64.             allObjects[updated.referenceImage.name].transform.position = updated.transform.position;
    65.             allObjects[updated.referenceImage.name].transform.rotation = updated.transform.rotation;
    66.         }
    67.     }
    68. }
    69.  
     
    artanasia, Cubixrube, HEKADE and 3 others like this.
  11. anubishs

    anubishs

    Joined:
    Apr 8, 2019
    Posts:
    5

    I've tried this, but nothing spawns. Don't know if there's a step missing or something.
     
  12. Markus_T

    Markus_T

    Joined:
    Jan 23, 2014
    Posts:
    8
    If you have a prefab in the AR Tracked Image Manager in the AR Session Origin (which I suggested setting to None), does that show up over your tracking images? If not, then you have problem that precedes what my sample script is doing.
    Also, keep in mind that the script I posted doesn't instantiate object from prefabs, so the objects need to be in the scene when you build. That isn't necessarily the best practice but for the sample script, shows how things work.
     
    HEKADE likes this.
  13. derfabs

    derfabs

    Joined:
    Jun 6, 2018
    Posts:
    2
    Thanks for your code, Markus, it works great. Yet, it only scans each picture once. Do you have any idea how to make it scan the same picture several times?
     
  14. Markus_T

    Markus_T

    Joined:
    Jan 23, 2014
    Posts:
    8
    I sorry, but I don't understand what you're trying to do. Can you give an example of what you'd like to have happen?
     
    HEKADE likes this.
  15. derfabs

    derfabs

    Joined:
    Jun 6, 2018
    Posts:
    2
    I want to scan a picture, activate its objects, and, when the next picture is scanned, deactivate the GOs of the former image. That's working so far. Yet, what's not possible, is to rescan the first image and reactivate the objects of the first scanned image.

    I adapted your code a little bit to deactivate the first GO to be able to deactivate this GO and added a debug Text to track, where problems could be.

    Code (CSharp):
    1. public class DifferentImageTracking : MonoBehaviour
    2. {
    3.     [Header("The length of this list must match the number of images in Reference Image Library")]
    4.     public List<GameObject> ObjectsToPlace;
    5.     public Text debug;
    6.     public GameObject preloadedImage;
    7.     private int refImageCount;
    8.     private Dictionary<string, GameObject> allObjects;
    9.     private ARTrackedImageManager arTrackedImageManager;
    10.     private IReferenceImageLibrary refLibrary;
    11.  
    12.     void Awake()
    13.     {
    14.         arTrackedImageManager = GetComponent<ARTrackedImageManager>();
    15.         debug.text = "Awake";
    16.     }
    17.  
    18.     private void OnEnable()
    19.     {
    20.         arTrackedImageManager.trackedImagesChanged += OnImageChanged;
    21.  
    22.     }
    23.  
    24.     private void OnDisable()
    25.     {
    26.         arTrackedImageManager.trackedImagesChanged -= OnImageChanged;
    27.     }
    28.  
    29.     private void Start()
    30.     {
    31.         refLibrary = arTrackedImageManager.referenceLibrary;
    32.         refImageCount = refLibrary.count;
    33.         LoadObjectDictionary();
    34.         debug.text = "start";
    35.     }
    36.  
    37.     void LoadObjectDictionary()
    38.     {
    39.         allObjects = new Dictionary<string, GameObject>();
    40.         for (int i = 0; i < refImageCount; i++)
    41.         {
    42.             allObjects.Add(refLibrary[i].name, ObjectsToPlace[i]);
    43.             ObjectsToPlace[i].SetActive(false);
    44.             debug.text = "Dictionary loaded";
    45.         }
    46.     }
    47.  
    48.     void ActivateTrackedObject(string _imageName)
    49.     {
    50.         allObjects[_imageName].SetActive(true);
    51.         debug.text = "scanned" + _imageName;
    52.         if (preloadedImage != allObjects[_imageName])
    53.         { preloadedImage.SetActive(false);
    54.             debug.text = "scannedandreplaced with" + allObjects[_imageName];
    55.          
    56.         };
    57.         preloadedImage = allObjects[_imageName];
    58.        
    59.  
    60.     }
    61.  
    62.  
    63.     public void OnImageChanged(ARTrackedImagesChangedEventArgs _args)
    64.     {
    65.         foreach (var addedImage in _args.added)
    66.         {
    67.             ActivateTrackedObject(addedImage.referenceImage.name);
    68.            
    69.         }
    70.  
    71.         foreach (var updated in _args.updated)
    72.         {
    73.             allObjects[updated.referenceImage.name].transform.position = updated.transform.position;
    74.             allObjects[updated.referenceImage.name].transform.rotation = updated.transform.rotation;
    75.         }
    76.     }
    77. }
    78.  
    79.  
     
  16. Mr_Jigs

    Mr_Jigs

    Joined:
    Apr 18, 2015
    Posts:
    69
    Are you using iOS version 13.3.1 by any chance? One of my devices was auto updated to 13.3.1 and the "re-scanning" of images stopped working. As far as I have been able to determine "trackedImagesChanged" does not set the event "added" more then once in this particular version of iOS. Previously I was able to rely on the "added" event appearing after swapping images. But that stopped working. Since I was working on an application that needed to go to an event I had to create a hack where I basically do the check if an image has been added in the updated section.
     
  17. Markus_T

    Markus_T

    Joined:
    Jan 23, 2014
    Posts:
    8
    On of the problems with arfoundation is that args.removed is not reported, so it is not easy to know when the tracking has been lost on an image. args.added is only called once per image and after that you only get args.updated information Therefore, I think that to do what you're trying to achieve you'll have to be tricky with the tracking.

    This has been reported as a bug, and you can follow that at these links...

    https://github.com/Unity-Technologies/arfoundation-samples/issues/365
    https://github.com/Unity-Technologies/arfoundation-samples/issues/261
     
    HEKADE likes this.
  18. mitchell320

    mitchell320

    Joined:
    Nov 12, 2019
    Posts:
    2
    Is this a feature of ARFoundation that will be added soon?
     
  19. KirillKuzyk

    KirillKuzyk

    Joined:
    Nov 4, 2013
    Posts:
    690
    You don't need two prefabs. The idea of changing Image Reference Library at runtime is fairly simple: you disable the ARTrackedImageManager, set a new library, then enable it again. Please refer to this example on how to do it:
    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEngine.XR.ARFoundation;
    3. using UnityEngine.XR.ARSubsystems;
    4.  
    5.  
    6. public class ImageTrackingLibrarySwitchTest : MonoBehaviour {
    7.     [SerializeField] XRReferenceImageLibrary firstLibrary = null, secondLibrary = null;
    8.     [SerializeField] ARTrackedImageManager manager = null;
    9.  
    10.     int curLibIndex = 0;
    11.  
    12.  
    13.     void Update() {
    14.         if (Input.GetMouseButtonUp(0)) {
    15.             SwitchImageLibrary();
    16.         }
    17.     }
    18.  
    19.     public void SwitchImageLibrary() {
    20.         curLibIndex = curLibIndex == 0 ? 1 : 0;
    21.         Debug.Log("setting lib with index " + curLibIndex);
    22.         manager.enabled = false;
    23.         var libs = new[] {firstLibrary, secondLibrary};
    24.         manager.referenceLibrary = manager.CreateRuntimeLibrary(libs[curLibIndex]);
    25.         manager.enabled = true;
    26.     }
    27. }
    28.  
     
unityunity