Multi Image Tracking ARFoundation

Background

Augmented Reality is a technology that has really taken the world by storm.
I was fortunate enough to have worked on some AR apps early in my career and it has been amazing watching how Unity has evolved into one of the defacto engines for building MR content.
Back in 2014, I used Unity and Vuforia to do basic image tracking and displaying a 3D model in AR.
Nowadays, we are spoilt with a host of amazing free tools that’s built right into Unity!

AR Foundation

AR Foundation is Unity’s framework that provides the high-level AR functionalty.
Instead of working directly with ARKit (Apple) and ARCore (Android) we can use a single framwork, whilst being able to deploy to both Android and Apple.
More info here

Goal

I wanted to replicate what I did using Vuforia in the past, but using AR Foundation instead.

  • Have a bunch of QR codes as reference images (‘markers’)
  • Display a 3D model once the marker is scanned

Result

  • The scene is made up of:
    • Here, the ARTrackedImageManager does all the heavy lifting
    • You provide it with a ReferenceImageLibrary – which contains your images you want to use as markers (QR codes in my case)
    • Provide it with a Prefab that will be spawned once the marker is tracked
    • Example: Map the GUID for each image in the XRReferenceImageLibrary to a GameObject – this specific example, order mattters.
      • Then once the trackedImagesChanged event is raised on the ARTrackedImageManager:
          // activate an image that was added
          foreach(ARTrackedImage image in obj.added)
          {
              GameObject characterPrefab;
              if(TryGetCharacterPrefab(image.referenceImage.guid, out characterPrefab))
              {
                  GameObject spawndedCharacter = Instantiate(characterPrefab, 
                  image.transform.position, 
                  image.transform.rotation);
                  this.m_SpawnedCharacters.Add(image.referenceImage.guid, spawndedCharacter);
                  spawndedCharacter.SetActive(true);
              }
          }
      
          // tracking has updated
          foreach (ARTrackedImage image in obj.updated)
          {
              if(image.trackingState == TrackingState.Tracking)
              {                
                  // update tracked image's position and rotation
                  if (TryGetSpwanedCharacter(image.referenceImage.guid, out spwanedCharacterGO))
                  {
                      spwanedCharacterGO.transform.SetPositionAndRotation(
                          image.transform.position, image.transform.rotation);
                  }
              }
              // image is no longer tracked, disable
              else
              {
                  if (TryGetCharacterPrefab(image.referenceImage.guid, out spwanedCharacterGO))
                  {
                      spwanedCharacterGO.SetActive(false);
                  }
              }
          }

Future

There are some improvements that I could make to this simple project:

  • Better handling of when the image looses tracking
  • Add some interaction perhaps

Resources