How to Create and Load Targets in Unity

This article presents the ways in which targets and target databases can be created and loaded in Unity. In the Unity Editor, targets can be configured in the scene at authoring time. This can be done either directly from an image asset or from a database created on the Vuforia Target Manager. Programmatically, three principal classes are used to load/unload and activate/deactivate databases and to create targets at runtime:

In addition, your Vuforia developer account can be used to create and manage your target databases in the Target Manager on the Vuforia developer webpage. See the article Getting Started with the Vuforia Target Manager for more information.

Video: How to create and load targets in Unity from a texture asset, a script, and a URL

Follow the video tutorial on how to create and load targets in Unity from a texture asset, from a script, and from a URL. Or, consult this guide for a step by step instruction and available code examples.

 

If you are looking for how to do this in native, please refer to How to Create and Modify Targets in Native.

 

How to create an Image Target from a texture asset in the Unity Editor

There are two ways in which Image Target databases can be generated.

  1. Using an image asset in the Unity Editor to create an Instant Image Target
  2. Using the Vuforia Target Manager

This section will explain how to create an image target directly in the Unity Editor.

  1. Open an empty Unity Project and enable Vuforia through the Package Manager.
  2. Create an ARCamera GameObject and insert a license from your Vuforia Developer account into the license key field found in VuforiaConfiguration in the ARCamera.
  3. Load a detailed JPG or PNG image into the assets folder.
  4. Create a new Vuforia Engine Image GameObject

  1. In the Inspector of the ImageTarget GameObject, make sure that Type is set to From Image.
  2. Drag the image file you wish to use to the empty box labeled Image and provide it with a name.
    1. It may that you need to set the image to “Read/Write Enabled” in the advanced import settings. The inspector will display a message if additional actions are required or if the image is in risk of being rescaled upon target creation.

NOTE: The expandable Advanced menu is for rescaling the imageTarget.

  1.  Place your AR content as a child on the ImageTarget GameObject and use Vuforia's Play Mode by pressing Play or deploy the app to your device.

How to create Instant Image Targets at Runtime from a file or Texture2D Objects

Addtionally, Instant Image Targets can be created at runtime in C#. Attach the following code example to the ARCamera GameObject to load an image file from the Streaming Assets folder.

  using UnityEngine;
  using UnityEngine.Networking;
  using System.Collections;
  using Vuforia;
  
  public class SideLoadIT : MonoBehaviour
  {
      void Start()
      {
          VuforiaARController.Instance.RegisterVuforiaStartedCallback(CreateImageTargetFromSideloadedTexture);
      }
  
      void CreateImageTargetFromSideloadedTexture()
      {
          var objectTracker = TrackerManager.Instance.GetTracker<ObjectTracker>();
  
          // get the runtime image source and set the texture to load
          var runtimeImageSource = objectTracker.RuntimeImageSource;
          runtimeImageSource.SetFile(VuforiaUnity.StorageType.STORAGE_APPRESOURCE, "Vuforia/myTarget.jpg", 0.15f, "myTargetName");
  
          // create a new dataset and use the source to create a new trackable
         var dataset = objectTracker.CreateDataSet();
          var trackableBehaviour = dataset.CreateTrackable(runtimeImageSource, "myTargetName");
  
          // add the DefaultTrackableEventHandler to the newly created game object
          trackableBehaviour.gameObject.AddComponent<DefaultTrackableEventHandler>();
  
          // activate the dataset
          objectTracker.ActivateDataSet(dataset);
  
          // TODO: add virtual content as child object(s)
      }
  }

The code example below will allow you to download a texture image from a web URL and generate an image target from it.

using UnityEngine;
using UnityEngine.Networking;
using System.Collections;
using Vuforia;

public class DownLoadIT : MonoBehaviour
{
    void Start()
    {
        StartCoroutine(CreateImageTargetFromDownloadedTexture());
    }

    IEnumerator CreateImageTargetFromDownloadedTexture()
    {
        using (UnityWebRequest uwr = UnityWebRequestTexture.GetTexture("https://myPage.com/myImage.jpg"))
        {
            yield return uwr.SendWebRequest();

            if (uwr.isNetworkError || uwr.isHttpError)
            {
                Debug.Log(uwr.error);
            }
            else
            {
                var objectTracker = TrackerManager.Instance.GetTracker<ObjectTracker>();

                // Get downloaded texture once the web request completes
                var texture = DownloadHandlerTexture.GetContent(uwr);

                // get the runtime image source and set the texture
                var runtimeImageSource = objectTracker.RuntimeImageSource;
                runtimeImageSource.SetImage(texture, 0.15f, "myTargetName");

                // create a new dataset and use the source to create a new trackable
                var dataset = objectTracker.CreateDataSet();
                var trackableBehaviour = dataset.CreateTrackable(runtimeImageSource, "myTargetName");

                // add the DefaultTrackableEventHandler to the newly created game object
                trackableBehaviour.gameObject.AddComponent<DefaultTrackableEventHandler>();

                // activate the dataset
                objectTracker.ActivateDataSet(dataset);

                // TODO: add virtual content as child object(s)
            }
        }
    }
}

Loading a database created with the Vuforia Target Manager at runtime

NOTE: You can call "Exists" without specifying a storage type. The assumption, then, is that your device database has been bundled with the application in StreamingAssets/Vuforia.

  1. Check whether the file at the given storage location exists using DataSet.Exists()
  2. Request an ObjectTracker instance from TrackerManager
  3. Create a new DataSet instance using ObjectTracker.CreateDataSet()
  4. Load a dataset file from its storage location using DataSet.Load()

The same storage type rules apply as for Exists.

Activating a database

Use the objectTracker instance to activate a dataset by calling ObjectTracker.ActivateDataSet(DataSet dataset);

// Load and activate a data set at the given path.
private bool LoadDataSet(string dataSetPath, DataSet.StorageType storageType)
{
    // Check if the data set exists at the given path.
    if (!DataSet.Exists(dataSetPath, storageType))
    {
        Debug.LogError("Data set " + dataSetPath + " does not exist.");
        return false;
    }

    // Request an ImageTracker instance from the TrackerManager.
    ObjectTracker objectTracker = TrackerManager.Instance.GetTracker();

    // Create a new empty data set.
    DataSet dataSet = objectTracker.CreateDataSet();

    // Load the data set from the given path.
    if (!dataSet.Load(dataSetPath, storageType))
    {
        Debug.LogError("Failed to load data set " + dataSetPath + ".");
        return false;
    }

    // (Optional) Activate the data set.
    objectTracker.ActivateDataSet(dataSet);

    return true;
}

How to size an Image Target at Runtime

Just as it is possible to create and activate device databases at runtime, so it is possible to change the size of a target, in this case an Image Target.

The sample code:

using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using Vuforia;

public class TargetInfo : MonoBehaviour
{
    void OnGUI()
    {
        StateManager sm = TrackerManager.Instance.GetStateManager();
        if (GUI.Button(new Rect(50, 50, 200, 40), "Size Up"))
        {
            ObjectTracker tracker = TrackerManager.Instance.GetTracker();
            var activeDataSets = tracker.GetActiveDataSets().ToList();
            foreach (DataSet ds in activeDataSets)
            {
                // Deactivate Dataset before changing the target size
                tracker.DeactivateDataSet(ds);
                foreach (Trackable trackable in ds.GetTrackables())
                {
                    if (trackable is ImageTarget)
                    {
                        ImageTarget it = trackable as ImageTarget; Vector2 old_size = it.GetSize();
                        Vector2 new_size = new Vector2(1.5f * old_size.x, 1.5f * old_size.y); 
                        it.SetSize(new_size);
                    }
                }
                // Re-activate dataset
                tracker.ActivateDataSet(ds);
            }
        }

        foreach (TrackableBehaviour tb in sm.GetActiveTrackableBehaviours())
        {
            if (tb is ImageTargetBehaviour)
            {
                ImageTargetBehaviour itb = tb as ImageTargetBehaviour;
                float dist2cam = (itb.transform.position - Camera.main.transform.position).magnitude;
                ImageTarget it = itb.Trackable as ImageTarget; Vector2 size = it.GetSize();
                GUI.Box(new Rect(50, 100, 300, 40), it.Name + " - " + size.ToString() + "\nDistance to camera: " + dist2cam);
            }
        }
    }
}