Working with Vuforia Engine and Unity

This article holds common how-to guides for authoring digital content for your Vuforia Engine targets. Learn how to add content at runtime, swap 3D models on a target or implement on-screen interaction logic for intuitive control for your users.

How to Dynamically Add Content to Targets in Unity

The following example demonstrates how you can augment an Image Target with a custom 3D model that is instantiated at run time, upon target detection, using Vuforia Engine. The script does the following: it dynamically adds a 3D model to the Astronaut Image Target.

Follow these steps:

  1. Open or create a Unity project, add an ImageTarget GameObject. Either import the default sample database with the Astronaut image or import and select your custom database with an Image Target.
  2. In the Project View, under the Assets folder, create a subfolder called Prefabs.
  3. Add a prefab object to the Prefabs folder. There are many ways to create custom prefabs to represent 3D objects. For instance, you could:
    • Create a simple Cube GameObject in your scene view and then drag it from the scene view into the Prefabs folder in the Project view,
      OR
    • Import a 3D model in a format supported by Unity (such as FBX, OBJ, DAE, or 3DS). Refer to the Unity website for details on how to create Prefabs from 3D models from various file formats.
  4. Create a C# script, call it MyPrefabInstantiator, and attach it to the Astronaut Image Target.
  5. Copy the following code into the script and then save the script:
using UnityEngine;
using Vuforia;

public class MyPrefabInstantiator : DefaultObserverEventHandler
{
    public GameObject myModelPrefab;

    GameObject mMyModelObject;

    protected override void OnTrackingFound()
    {
        Debug.Log("Target Found");

        // Instantiate the model prefab only if it hasn't been instantiated yet
        if (mMyModelObject == null) 
            InstantiatePrefab();

        base.OnTrackingFound();
    }

    void InstantiatePrefab()
    {
        if (myModelPrefab != null)
        {
            Debug.Log("Target found, adding content"); 
            mMyModelObject = Instantiate(myModelPrefab, mObserverBehaviour.transform);
            mMyModelObject.transform.localScale = new Vector3(0.1f, 0.1f, 0.1f);
            mMyModelObject.SetActive(true);
        }
    }
}

The MyPrefabInstantiator class inherits from the DefaultObserverEventHandler class, that takes care of handling events when the target is detected. At that point, the Prefab 3D model gets instantiated and gets attached on the Image Target.

  1. Return to the Unity scene view and click on the Astronaut Image Target, in the inspector you will see that the MyPrefabInstantiator script exposing a field called My Model Prefab.
    • Select your prefab in the Prefabs folder (in the project view) and drag it onto the My Model Prefab field in the MyPrefabInstantiator script component..
  2. Save the project, and then build and run the app or use the Play Mode. As soon as the Image Target is detected and TRACKED, your prefab 3D model should appear on top of it.
  3. If the model size is either too small or too big, you can go to the script code and adjust the localScale values.

How to Dynamically Swap a 3D Model of a Target in Unity

This section explains how you can swap the 3D model of an Image Target (or other target) with a different 3D model at run time.

  1. Open or create a Unity project, add an ImageTarget GameObject.
  2. Add a 3D model as a child of the Image Target, for example a sphere.
  3. Create a C# script, name it ModelSwapper. This script will display a button on top of the camera view that when pressed, lets you swap one model with another 3D model. In our example, this will be a cube.
  4. Insert the following code into the ModelSwapper script:
using UnityEngine;
using Vuforia;

public class ModelSwapper : MonoBehaviour
{
    public ObserverBehaviour mTarget;
    private bool mSwapModel = false;

    // Use this for initialization
    void Start()
    {
        if (mTarget == null)
        {
            Debug.Log("Warning: Target not set !!");
        }
    }
    // Update is called once per frame
    void Update()
    {
        if (mSwapModel && mTarget != null)
        {
            SwapModel();
            mSwapModel = false;
        }
    }
    void OnGUI()
    {
        if (GUI.Button(new Rect(50, 50, 120, 40), "Swap Model"))
        {
            mSwapModel = true;
        }
    }
    private void SwapModel()
    {
        // Disable any pre-existing augmentation
        GameObject mExistingModel = mTarget.gameObject;
        
        for (int i = 0; i < mExistingModel.transform.childCount; i++)
        {
            Transform child = mExistingModel.transform.GetChild(i);
            child.gameObject.SetActive(false);
        }

        // Create a simple cube object
        GameObject cube = GameObject.CreatePrimitive(PrimitiveType.Cube);

        // Re-parent the cube as child of the trackable gameObject
        cube.transform.parent = mTarget.transform;

        // Adjust the position and scale
        // so that it fits nicely on the target
        cube.transform.localPosition = new Vector3(0, 0.2f, 0);
        cube.transform.localRotation = Quaternion.identity;
        cube.transform.localScale = new Vector3(0.1f, 0.1f, 0.1f);
        // Make sure it is active
        cube.SetActive(true);
    }
}
  1. Attach the script to the ARCamera GameObject in your scene view,
  2. In the inspector view, drag your target GameObject to the field mTarget.
  3. Test the script with Play Mode and press the Swap model button to disable the sphere and create a cube as a child of the target.

How to Drag an Augmentation using Touch Input

This section provides the sample code of a script that lets users drag an AR object on the screen with their finger,

  1. Open or create a new Unity Project. Add the ARCamera and a Vuforia target GameObject.
  2. Add a 3D sphere or other 3D content as a child to the target GameObject. The content must have a mesh collider.
  3. Create a new script named DragObject.cs. Add the following code to it and attach the script to the ARCamera. The script enables users to touch and drag an object around
using UnityEngine;

public class DragObject : MonoBehaviour
{
    private Transform pickedObject = null;
    private Vector3 lastPlanePoint;

    // Update is called once per frame
    void Update()
    {
        Plane targetPlane = new Plane(transform.up, transform.position);

        foreach (Touch touch in Input.touches)
        {
            // Gets the ray at position where the screen is touched
            Ray ray = Camera.main.ScreenPointToRay(touch.position);

            // Gets the position of ray along plane
            float dist = 0.0f;

            // Intersects ray with the plane. Sets dist to distance along the ray where intersects
            targetPlane.Raycast(ray, out dist);

            // Returns point dist along the ray.
            Vector3 planePoint = ray.GetPoint(dist);

            // True if finger touch began. If ray intersects collider, set pickedObject to transform of collider object
            if (touch.phase == TouchPhase.Began)
            {
                // Struct used to get info back from a raycast
                RaycastHit hit = new RaycastHit();
                if (Physics.Raycast(ray, out hit, 1000))
                { // True when Ray intersects collider. If true, hit contains additional info about where collider was hit
                        pickedObject = hit.transform;
                    lastPlanePoint = planePoint;
                }
                else
                {
                    pickedObject = null;
                }
                // Move Object when finger moves after object selected.
            }
            else if (touch.phase == TouchPhase.Moved)
            {
                if (pickedObject != null)
                {
                    pickedObject.position += planePoint - lastPlanePoint;
                    lastPlanePoint = planePoint;
                }
                // Set pickedObject to null after touch ends.
            }
            else if (touch.phase == TouchPhase.Ended)
            {
                pickedObject = null;
            }
        }
    }
}