Create and Load Targets in Unity

Use the Vuforia Engine C# API to create, load and modify Vuforia targets at runtime. You can create Vuforia targets from databases stored locally on the device or download them from a server.

Introduction

Create and load targets at runtime with API scripting. Scenarios for this could, for example, be solely for tracking targets, switching between targets, or receiving databases at runtime.

See also Instant Image Targets that lets you generate an Image Target from a suitable image source rather than from a database.

When you create a Vuforia target at runtime, you load the database and assets from the device’s local storage. In Unity projects, this is generally done by placing the needed files - .xml and .dat files – in the StreamingAssets/Vuforia folder before building the app. At runtime, Vuforia targets are loaded and created from the local storage on the main thread. If you are dealing with larger databases or wish to keep the main thread free, you can use the Async creator functions.

For details on loading assets from device storage, see Loading from an SD card.

See also Building Large Vuforia Engine Apps in Unity if you are building a large application.

Create an Image Target from a Device Database at Runtime

Similar to other instant Image Target creation methods, you specify a storage path when loading from a local directory. For larger apps, the device database may be bundled with the application in StreamingAssets/Vuforia. Also, note that the paths might differ dependent on the platform you are building to. In the following example, we only load the data needed for tracking an Image Target.

using System.IO;
using UnityEngine;
using Vuforia;

public class CreateFromDatabase : MonoBehaviour
{
    string dataSetPath = "Vuforia/mydevicedatabase.xml";
    string targetName = "mars_target_images_astronaut";

    // Start is called before the first frame update
    void Start()
    {
        VuforiaApplication.Instance.OnVuforiaInitialized += OnVuforiaInitialized;
    }

    void OnVuforiaInitialized(VuforiaInitError error)
    {
        if (error == VuforiaInitError.NONE)
            OnVuforiaStarted();
    }

    // Load and activate a data set at the given path.
    void OnVuforiaStarted()
    {
        // Create an Image Target from the database.
        var mImageTarget = VuforiaBehaviour.Instance.ObserverFactory.CreateImageTarget(
            dataSetPath,
            targetName);
        mImageTarget.OnTargetStatusChanged += OnTargetStatusChanged;
    }

    void OnTargetStatusChanged(ObserverBehaviour behaviour, TargetStatus status)
    {
        Debug.Log($"target status: {status.Status}");
    }
}

To load and track other targets, the above script can be modified by replacing the dataSetPath and targetName with a different dataset, and changing the CreateImageTarget() to e.g., CreateModelTarget(), CreateAreaTarget(), etc.. To add content to a target at runtime, see Working with Vuforia Engine in Unity.

Create Multiple Targets from a Device Database at Runtime

The following code snippet creates an Image Target for each provided target name in a single Device Database. OnTargetStatusChanged() reports which of the Image Targets is currently tracked. Attach this script to the ARCamera and make sure the Device Database and target names are correctly listed as they are case sensitive. The target names are available in the dataset XML file.

using UnityEngine;
using Vuforia;
public class LoadMultipleTargetsFromDatabase : MonoBehaviour
{
    // List of target names
    static readonly string[] targetNames = new[] { "Astronaut", "Oxygen", "Fissure", "Drone" };

    void Start()
    {
        VuforiaApplication.Instance.OnVuforiaInitialized += OnVuforiaInitialized;
    }

    void OnVuforiaInitialized(VuforiaInitError error)
    {
        // Create an Image Target for each target name in device database
        foreach (var target in targetNames)
        {
            var itBehaviour = VuforiaBehaviour.Instance.ObserverFactory.CreateImageTarget("Vuforia/VuforiaMars_Images.xml", target);
            Debug.Log("target created: " + target);
            itBehaviour.OnTargetStatusChanged += OnTargetStatusChanged;
        }
    }

    void OnTargetStatusChanged(ObserverBehaviour behaviour, TargetStatus status)
    {
        Debug.Log($"target status: {behaviour.TargetName} {status.Status}");
    }
}

Loading and creating targets is in this example done on the main thread, but if you plan to create many targets with a single call, we advise to use asynchronous calls.

Create Targets Asynchronously

If you have a device database with large targets that may time to load, you can create them using the Async methods from the ObserverFactory. These methods place the task on a background thread freeing up the main thread for UI and other updates. The following example loads the database path and target names and assigns the creation process to an await operator which returns the loaded targets once completed. Replace the CreateImageTargetAsync with any of the other asynchronous functions to create targets from other Vuforia features.

using UnityEngine;
using Vuforia;

public class AsyncTargetLoading : MonoBehaviour
{
    static readonly string[] targetNames = new[] { "mars_target_images", "mars_target_images_oxygen", "mars_target_images_fissure", "mars_target_images_drone" };
    private string databasePath = $"{Application.streamingAssetsPath}/Vuforia/My_Device_Database.xml";

    void Start()
    {
        VuforiaApplication.Instance.OnVuforiaInitialized += OnVuforiaInitialized;
    }

    void OnVuforiaInitialized(VuforiaInitError error)
    {
        if(error == VuforiaInitError.NONE)
        {
            CreateIT();
        }
    }
    // Start is called before the first frame update
    public async void CreateIT()
    {

        // Create an Image Target for each target name in dataset
        foreach (var target in targetNames)
        {
            var itBehaviour = await VuforiaBehaviour.Instance.ObserverFactory.CreateImageTargetAsync(databasePath, target);
            Debug.Log("target created: " + target);
            itBehaviour.OnTargetStatusChanged += OnTargetStatusChanged;
        }
    }
}

Use the same approach to create other targets asynchronously, e.g., CreateAreaTargetAsync()CreateModelTargetAsync()CreateVuMarkBehaviourAsync(), etc..

Activate Targets at Runtime

When a Vuforia Target is created at runtime, it’s enabled by default. You can enable and disable your targets at runtime if you for example wish to switch between loaded targets.

Attach the script to an ImageTarget GameObject with its Image Target Behaviour component disabled.

using UnityEngine;
using Vuforia;

public class ActivateTargets : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        VuforiaApplication.Instance.OnVuforiaStarted += ActivateTarget;
    }

    void ActivateTarget()
    {
        ImageTargetBehaviour imageTarget = GetComponent<ImageTargetBehaviour>();
        imageTarget.enabled = true;
    }
}

To disable a Vuforia target, change the imageTarget.enabled to false.

Set the Size of an Image Target at Runtime

Modify targets at runtime and its child objects to adjust the AR experience. In this example, an Image Target is scaled with a button press. Your Unity scene requires an Image Target GameObject with a cube as a child and a button UI for executing SizeMyTarget().

Attach the following script to the Image Target GameObject and assign it to the button’s OnClick() event with the method.

The sample code:

using UnityEngine;
using Vuforia;

public class SizeImageTarget : MonoBehaviour
{
    ImageTargetBehaviour mImageTarget;
    public float scale = 2;

    public void SizeMyTarget()
    {
        mImageTarget = GetComponent<ImageTargetBehaviour>();
        if (!mImageTarget)
        {
            Debug.LogError("Cannot set scale, missing target input");
            return;
        }

        // First deactivate the Image Target
        mImageTarget.enabled = false;

        // Query the current Image Target size
        Vector2 currentSize = mImageTarget.GetSize();

        // Set the new size with a scale factor to height or width
        float width = currentSize.x;
        float newSize = scale * width;

        mImageTarget.SetWidth(newSize);

        // Re-activate the Image Target
        mImageTarget.enabled = true;
    }
}

Can this page be better?
Share your feedback via our issue tracker