Create a Pokémon GO Style Augmented Reality Game With Vuforia: Image Targets

In this tutorial we’ll dive back into the Vuforia Augmented Reality (AR) library, exploring one of its most interesting resources—the Image Target. We’ll expand on the Shoot the Cubes game that we created in earlier lessons, adding a new level where the player needs to defend their base from attacking cubes.

Create a Pokémon GO Style Augmented Reality Game With Vuforia: Image Targets

This tutorial can be completed alone, although if you want an introduction to AR with Vuforia and Unity3D, check out the earlier posts in the series.

  • Create a Pokémon GO Style Augmented Reality Game With Vuforia: Image Targets
    Mobile Development
    Pokémon GO Style Augmented Reality With Vuforia
    Tin Megali
  • Create a Pokémon GO Style Augmented Reality Game With Vuforia: Image Targets
    Mobile Development
    Create a Pokémon GO Style Augmented Reality Game With Vuforia
    Tin Megali

Image Targets

Any kind of image can be a Vuforia Image Target. However, the more detailed and intricate the image, the better it will be recognized by the algorithm.

A lot of factors will be part of the recognizing calculation, but basically the image must have a reasonable level of contrast, resolution, and distinguishing elements. A blue sky photograph wouldn’t work very well, but a picture of some grass would work gracefully. Image Targets can be shipped with the application, uploaded to the application through the cloud, or directly created in the app by the user.

Adding a Target

Let’s begin by adding an ImageTarget element to our Unity project.

First, download the course assets from the button in the sidebar. Then, in your Unity project, create a new scene called DefendTheBase: in the Project window, select the Scenes folder and click on Create > Scene. Now open that scene and remove all the default scene objects from the hierarchy.

Next we’ll add a light and camera. Click on Add > Light > Directional Light to add a directional light. Select this new light and set Soft Shadow as the Shadow Type option.

After that, drag and drop an ARCamera object from Vuforia > Prefabs. Select the ARCamera object and in the inspector panel, set the App License Key created on the Vuforia developer page (see the first tutorial for instructions). Select DEVICE_TRACKING for the World Center Mod.

Finally, drag and drop an ImageTarget to the hierarchy from Vuforia > Prefabs.

Now we have to add a Vuforia Database. First, navigate to https://developer.vuforia.com/target-manager. Click on Add Database and choose a name.

There are three types of Database to choose from:

  1. Device: The Database is saved on the device and all targets are updated locally.
  2. Cloud: Database on the Vuforia servers.
  3. VuMark: Database exclusive to VuMark targets. It is also saved on the device.

In this case, choose the Device option and click on create.

Select the new database so we can start adding targets to it. Now it is time to add targets to the database. For now, we’ll just use the Single Image option.

Navigate to the previously downloaded files, pick ImageTarget1, and set its Width to 1 and click on Add. (Note: If you prefer to create your own Image Target, read the guide first.)

Create a Pokémon GO Style Augmented Reality Game With Vuforia: Image Targets

Now you can download the database, selecting Unity Editor as the chosen platform. Open the file and select all elements to be imported. We must also prepare our Unity scene to recognize the ImageTarget with this database we have created.

In the Unity editor, click on the ImageTarget object. First, find and expand Image Target Behavior in the object inspector. Select a Type of Predefined. Choose the image target we created earlier for Database. Finally, make sure that the Enable Extended Tracking and Enable Smart Terrain options are both disabled.

Create a Pokémon GO Style Augmented Reality Game With Vuforia: Image Targets

The ImageTarget prefab is made of a series of components, including some scripts like Image Target Behavior, Turn Off Behavior, and Default Tracker Event Handler. If you want to deeply understand how the system works, read those scripts and try to understand their relationship to other components.

For this tutorial, we won’t dig too deep, though. We’ll only need to concentrate on the Default Tracker Event Handler, which receives calls when the image target tracking status changes. So let’s use this script as a base to create our own script behavior.

Create a copy of this script that we can extend. First select Default Tracker Event Handler, click on options and select Edit Script. Now, make a copy of the script. If you’re using MonoDevelop, click File > Save As and save as ImageTargetBehavior, saving it in the Scripts folder.

The TargetBehaviorScript Script

We won’t need the Vuforia namespace in our script. Remove the line “namespace Vuforia” and the brackets. That means we’ll need to explicitly reference the Vuforia namespace when we want to access its classes:

using UnityEngine;
using System.Collections;
public class BaseScript : MonoBehaviour, Vuforia.ITrackableEventHandler
{
    // code here
}

The most important method in this class will be the OnTrackableStateChanged method that receives calls when the image target is found or lost by the camera device. According to the target status, it calls OnTrackingFound or OnTrackingLost, and we’ll need to edit those methods as well. But first, let’s think about how we want the image target to behave.

In this game, the user will defend a base that appears on an image target. Let’s consider the following game mechanics:

  • Once the target is recognized by the system, the base appears and enemies start to spawn and fly toward the base in a kamikaze style.
  • Every time an enemy hits the base, the base will take some damage and the enemy will be destroyed.
  • To win the game the user must shoot and destroy all enemies before the base is destroyed.
  • If the image target is lost (is no longer visible from the device camera), the game will start a countdown timer. If the timer gets to zero, the game is lost. While the target is lost, all enemies will stop advancing toward the base.

So we’ll need to adapt those game mechanics on top of what we built in the last tutorial. We’ll create the enemy spawning logic in the next section with an empty object named _SpawnController, using the same logic adopted in the first part of the game.

For now, let’s look at the tracking found logic.

private void OnTrackingFound ()
{
    EnableRendererAndCollider ();
	// Inform the system that the target was found
	StartCoroutine (InformSpawnCtr (true));
}

private void OnTrackingLost ()
{
	DisableRendererAndCollider ();
	// Inform the system that the target was lost
	StartCoroutine (InformSpawnCtr (false));
}

// inform SpanController that base was founded
private IEnumerator InformSpawnCtr (bool isOn)
{
	// move spawning position
	GameObject spawn = GameObject.FindGameObjectWithTag ("_SpawnController");

	yield return new WaitForSeconds (0.2f);

	// inform SpanController
	if (isOn) {
		spawn.GetComponent<SpawnScript2> ().BaseOn (transform.position);
	} else {
		spawn.GetComponent<SpawnScript2> ().BaseOff ();
	}
}

Back in the Unity editor, we can create the base object that will be spawned by the spawn controller.

First, on the ImageTarget object, disable the Default Trackable Event Handler script.

Next, click on Add Component and select the Target Behavior Script. From the Hierarchy panel, right click on ImageTarget and create a new cube named “Base”. This cube should be inserted inside the ImageTarget object.

Make sure that the Base has Box Collider and Mesh Renderer enabled.

Optionally, you could also insert a Plane object inside the ImageTarget using the ImageTarget submitted earlier in Vuforia as a texture. This would create an interesting effect, projecting shadows from the target and creating a richer experience.

Create a Pokémon GO Style Augmented Reality Game With Vuforia: Image Targets

Adapting the SpawnScript

Now we will adapt the _SpawnController used in the last tutorial. Save the current scene and open ShootTheCubesMain from the last tutorial. In the Hierarchy panel, select the _SpawnController and drag it to the Prefabs folder to make it a Unity Prefab.

Save this new scene and reopen DefendTheBase. Drag _SpawnController from the prefabs folder to the Hierarchy panel. With the _SpawnController selected, click on Add Tag on the Inspector panel. Name the new tag _SpawnController and apply it to the object.

In the Project window, select the Cube element in the Prefab folder and set its Tag, back on its inspector, to ‘Enemy’.

Create a Pokémon GO Style Augmented Reality Game With Vuforia: Image Targets

Finally, open the Scripts folder and open SpawnScript. We need to make this script adapt itself to the loaded scene.

using UnityEngine;
using UnityEngine.SceneManagement;
using System.Collections;
using System.Collections.Generic;

using Vuforia;

public class SpawnScript : MonoBehaviour
{

    #region VARIABLES
    private bool mSpawningStarted = false;

    // Cube element to spawn
    public GameObject mCubeObj;
    // Qtd of Cubes to be Spawned
    public int mTotalCubes = 10;

    private int mCurrentCubes	= 0;

    // Time to spawn the Cubes
    public float mTimeToSpawn	= 1f;   
    
    private int mDistanceFromBase = 5;

    private List<GameObject> mCubes;

    private bool mIsBaseOn;
    private Scene mScene;

    #endregion // VARIABLES


    #region UNITY_METHODS

    // Use this for initialization
    void Start ()
    {
        mScene = SceneManager.GetActiveScene();
        mCubes = new List<GameObject> ();

        if ( mScene.name == "ShootTheCubesMain" )
        {
            StartSpawn();
        }
    }

    // Update is called once per frame
    void Update ()
    {

    }

    #endregion // UNITY_METHODS

Next, we need to create two public methods to receive calls from TargetBehaviorScript when the target is found or lost:

  • BaseOn
    (Vector3 basePosition)
    will be called when the target is found by the camera and the Base object is shown. It will change the spawning position, start the process, and inform all cubes that were previously added to the stage that the base is visible.
  • The BaseOff() method will be used when the target is lost. It will stop the staging process and inform all cube elements that the base was lost.
#region PUBLIC_METHODS

    // Base was found by the tracker
	public void BaseOn (Vector3 basePosition)
	{
		Debug.Log ("SpawnScript2: BaseOn");

		mIsBaseOn = true;

		// change position
		SetPosition (basePosition);

		// start spawning process if necessary
		StartSpawn ();

		// inform all cubes on screen that base appeared
		InformBaseOnToCubes ();
	}

	// Base lost by the tracker
	public void BaseOff ()
	{	
		mIsBaseOn = false;
		mSpawningStarted = false;

		// inform all cubes on screen that base is lost
		InformBaseOffToCubes ();
	}

	#endregion // PUBLIC_METHODS

The SetPosition (System.Nullable<Vector3> pos) uses the target’s current position to modify the object x, y, and z axes, and it can also receive a null value when the scene loaded is ShootTheCubesMain.

#region PRIVATE_METHODS

    // We'll use a Coroutine to give a little
	// delay before setting the position
	private IEnumerator ChangePosition ()
	{
		Debug.Log ("ChangePosition");
		yield return new WaitForSeconds (0.2f);
		// Define the Spawn position only once

		// change the position only if Vuforia is active
		if (VuforiaBehaviour.Instance.enabled)
			SetPosition (null);
		
	}

	// Set position
	private void SetPosition (System.Nullable<Vector3> pos)
	{
		if (mScene.name == "ShootTheCubesMain") {
			// get the camera position
			Transform cam = Camera.main.transform;

			// set the position 10 units ahead of the camera position
			transform.position = cam.forward * 10;
		} else if (mScene.name == "DefendTheBase") {
			if (pos != null) {
				Vector3 basePosition = (Vector3)pos;
				transform.position = 
					new Vector3 (basePosition.x, basePosition.y + mDistanceFromBase, basePosition.z);
			}
		}

	}

InformBaseOnToCubes() and InformBaseOffToCubes() are responsible for informing all staged cubes of the current base status.

// Inform all spawned cubes of the base position
    private void InformBaseOnToCubes ()
	{
		//			Debug.Log("InformBaseOnToCubes");
		foreach (GameObject cube in mCubes) {
			cube.GetComponent<CubeBehaviorScript> ().SwitchBaseStatus (mIsBaseOn);
		}
	}

	// Inform to all cubes that the base is off
	private void InformBaseOffToCubes ()
	{
		//			Debug.Log("InformBaseOffToCubes");
		foreach (GameObject cube in mCubes) {
			cube.GetComponent<CubeBehaviorScript> ().SwitchBaseStatus (mIsBaseOn);
		}
	}

The SpawnLoop() and SpawnElement() methods are using almost the same logic as the last tutorial.

// Start spawning process
    private void StartSpawn ()
	{
		if (!mSpawningStarted) {
			// begin spawn
			mSpawningStarted = true;
			StartCoroutine (SpawnLoop ());
		}
	}

	// Loop Spawning cube elements
	private IEnumerator SpawnLoop ()
	{
		if (mScene.name == "ShootTheCubesMain") {
			// Defining the Spawning Position
			StartCoroutine (ChangePosition ());
		}

		yield return new WaitForSeconds (0.2f);
		// Spawning the elements
		while (mCurrentCubes <= (mTotalCubes - 1)) {
			// Start the process with different conditions
			// depending on the current stage name
			if (mScene.name == "ShootTheCubesMain" ||
			    (mScene.name == "DefendTheBase" && mIsBaseOn)) {

				mCubes.Add (SpawnElement ());
				mCubes [mCurrentCubes].GetComponent<CubeBehaviorScript> ().SwitchBaseStatus (mIsBaseOn);
				mCurrentCubes++;

			}

			yield return new WaitForSeconds (Random.Range (mTimeToSpawn, mTimeToSpawn * 3));
		}
	}

	// Spawn a cube
	private GameObject SpawnElement ()
	{
		// spawn the element on a random position, inside a imaginary sphere
		GameObject cube = Instantiate (mCubeObj, (Random.insideUnitSphere * 4) + transform.position, transform.rotation) as GameObject;
		// define a random scale for the cube
		float scale = Random.Range (0.5f, 2f);
		// change the cube scale
		cube.transform.localScale = new Vector3 (scale, scale, scale);
		return cube;
	}

	#endregion // PRIVATE_METHODS

Creating the Enemies

Now we’ll need to create some enemies. We’ll use the Cube object that we created in the last tutorial, making some modifications to its script.

In the Prefabs folder, add a Cube object to the hierarchy. Then select the object and edit the CubeBehaviorScript.

We’ll preserve almost the same logic in this script, but with the following differences:

  • The Cube will pursue the Base when the target is found by the camera.
  • When the Cube hits the Base, it will destroy itself and give some damage to the Base.
  • The script needs to know the name of the scene loaded and adapt itself accordingly.
using UnityEngine;
using UnityEngine.SceneManagement;
using System.Collections;

public class CubeBehaviorScript : MonoBehaviour {

    #region VARIABLES

	public float mScaleMax	= 1f;
	public float mScaleMin	= 0.2f;

	public int mCubeHealth	= 100;

	// Orbit max Speed
	public float mOrbitMaxSpeed = 30f;

	public float velocityToBase = 0.4f;
	public int damage = 10;

	// Orbit speed
	private float mOrbitSpeed;

	// Orbit direction
	private Vector3 mOrbitDirection;

	// Max Cube Scale
	private Vector3 mCubeMaxScale;

	// Growing Speed
	public float mGrowingSpeed	= 10f;
	private bool mIsCubeScaled	= false;

	private bool mIsAlive		= true;
	private AudioSource mExplosionFx;

	private GameObject mBase;
	private bool mIsBaseVisible = false;

	private Vector3 mRotationDirection;
	private Scene mScene;

	#endregion

If the scene’s name is DefendTheBase, it must find the Base object and start to move towards it.

#region UNITY_METHODS

    void Start () {
		// Get Scene name
		mScene = SceneManager.GetActiveScene();
		CubeSettings();
	}

	void Update () {
		// makes the cube orbit and rotate
		RotateCube();

		if ( mScene.name == "DefendTheBase" ) {
			// move cube towards the base, when it's visible
			MoveToBase ();
		}

		// scale cube if needed
		if ( !mIsCubeScaled )
			ScaleObj();
	}
	#endregion

The CubeSettings() also need to adapt according to the scene loaded. The Cube only orbits on the y-axis for the DefendTheBase scene.

#region PRIVATE_METHODS
    private void CubeSettings ()
	{
		// defining the orbit direction
		float x = Random.Range ( -1f, 1f );
		float y = Random.Range (-1f, 1f);
		float z = Random.Range ( -1f, 1f );

		// TODO update tutorial with new code
		// define settings according to scene name
		if ( mScene.name == "ShootTheCubesMain" )
		{
			mOrbitDirection = new Vector3( x, y, z );
		}
		else if ( mScene.name == "DefendTheBase" )
		{
			// orbit only on y axis
			mOrbitDirection = new Vector3 (0, y, 0);

			// scale size must be limited
			mScaleMin = 0.05f;
			mScaleMax = 0.2f;

			velocityToBase = 0.2f;
		}

		// rotating around its axis
		float rx = Random.Range (-1f, 1f);
		float ry = Random.Range (-1f, 1f);
		float rz = Random.Range (-1f, 1f);

		mRotationDirection = new Vector3 (rx, ry, rz);


		// defining speed
		mOrbitSpeed = Random.Range (5f, mOrbitMaxSpeed);

		// defining scale
		float scale = Random.Range (mScaleMin, mScaleMax);
		mCubeMaxScale = new Vector3 (scale, scale, scale);

		// set cube scale to 0, to grow it later
		transform.localScale = Vector3.zero;

		// getting Explosion Sound Effect
		mExplosionFx = GetComponent<AudioSource> ();
	}

We’ll add some new logic to the RotateCube() method. The cube objects will rotate around the base while the target is visible. When the target is not visible, they will continue to rotate around the Camera, using the same logic as in the last tutorial.

// Rotate the cube around the base
    private void RotateCube ()
	{
		// rotate around base or camera
		if (mIsBaseVisible && mBase != null && mIsAlive) {
			// rotate cube around base
			transform.RotateAround (
				mBase.transform.position, mOrbitDirection, mOrbitSpeed * Time.deltaTime);
		} else {
			transform.RotateAround (
				Camera.main.transform.position, mOrbitDirection, mOrbitSpeed * Time.deltaTime);
		}
		transform.Rotate (mRotationDirection * 100 * Time.deltaTime);
	}
    // Scale object from 0 to 1
    private void ScaleObj(){

		// growing obj
		if ( transform.localScale != mCubeMaxScale )
			transform.localScale = Vector3.Lerp( transform.localScale, mCubeMaxScale, Time.deltaTime * mGrowingSpeed );
		else
			mIsCubeScaled = true;
	}

To move the object toward the base, we’ll need to check first if the base is present, and then apply the position steps to the object.

	// Move the cube toward the base
	private void MoveToBase ()
	{
		// make the cube move towards the base only if base is present
		if (mIsBaseVisible && mIsAlive && gameObject != null && mBase != null) {
			float step = velocityToBase * Time.deltaTime;
			transform.position = Vector3.MoveTowards (transform.position, mBase.transform.position, step);
		}
	}

The DestroyCube() method is the same as before, but now we’ll add a new method—the TargetHit(GameObject) method—that will be called when the base is hit. Note that the BaseHealthScript referenced in TargetHit() hasn’t been created yet.

// make a damage on target
    private void TargetHit (GameObject target)
	{
		Debug.Log ("TargetHit: " + target.name);
		if (target.name == "Base") {
			// make damage on base
			MyBase baseCtr = target.GetComponent<MyBase> ();
			baseCtr.TakeHit (damage);
			StartCoroutine (DestroyCube ());
		}
	}

	// Destroy Cube
	private IEnumerator DestroyCube(){
		mIsAlive = false;

		mExplosionFx.Play();

		GetComponent<Renderer>().enabled = false;

		yield return new WaitForSeconds(mExplosionFx.clip.length);
		Destroy(gameObject);
	}

	#endregion

Finally, we’ll add the public methods to be called when the cube takes a hit, when it collides with the base, or when the base changes status.

#region PUBLIC_METHODS

    // Cube gor Hit
	// return 'false' when cube was destroyed
	public bool Hit( int hitDamage ){
		mCubeHealth -= hitDamage;
		if ( mCubeHealth >= 0 && mIsAlive ) {
			StartCoroutine( DestroyCube());
			return true;
		}
		return false;
	}

	public void OnCollisionEnter (Collision col)
	{
		TargetHit (col.gameObject);
	}

	// Receive current base status
	public void SwitchBaseStatus (bool isOn)
	{
		// stop the cube on the movement toward base
		mIsBaseVisible = isOn;
		if (isOn) {
			mBase = GameObject.Find ("Base");
		} else {
			mBase = null;
		}
	}

	#endregion

Controlling the Base Health

The enemies are being staged and flying toward the base, but they don’t cause any damage when they collide—neither to the base nor to the enemy. We need to create a script to respond to collisions and also to add a health bar to the screen, so the user knows how well they are doing.

Let’s begin adding the health bar. In the Hierarchy panel in the Unity editor, click on Create > UI > Slider. A new Canvas element will be added to the hierarchy. It contains UI elements, including the new Slider. Expand the Canvas and select the Slider.

Change the slider element name to UIHealth. In the Inspector panel, expand Rect Transform and set Width to 400 and Height to 40. Set Pos X to -220, Pos Y to 30, and Pos Z to 0.

Now expand the slider script in the hierarchy. Unselect the Interactable option. For Target Graphic, click on the small ‘dot’ on the right side and select the Background image.

  • Set the Min Value to 0 and Max Value to 100.
  • Select Whole Numbers.
  • Set Value to 100.

Create a Pokémon GO Style Augmented Reality Game With Vuforia: Image Targets

Now, expand the Slider panel to expose its child elements: Background, Fill Area, and Handle Slide Area.

  • Delete Handle Slide Area.
  • Select Background and set its Color to a darker shade of green, like #12F568FF.
  • Expand Fill Area and select the Fill object and set its color to #7FEA89FF.

This is how the Game Window should look with the health bar.

Create a Pokémon GO Style Augmented Reality Game With Vuforia: Image Targets

The Base Health Script

The code is very simple; it just subtracts the damage made by the enemies from the total amount of the base’s health. Once the health gets to zero, the player loses the game. It will also add a rotation animation to the Base. Create a new C# script called MyBase.

using UnityEngine;
using UnityEngine.UI;
using System.Collections;

public class MyBase : MonoBehaviour
{
    #region VARIABLE

	public float rotationSpeed = 10f;

	public int health = 100;
	public AudioClip explosionSoundFx;
	public AudioClip hitSoundFx;
	// TODO choose a different sound for the Hit

	private bool mIsAlive = true;
	private AudioSource mAudioSource;
	public Slider mHealthSlider;

	#endregion // VARIABLES


	#region UNITY_METHODS

	// Use this for initialization
	void Start ()
	{
		mAudioSource = GetComponent<AudioSource> ();
		mHealthSlider.maxValue = health;
		mHealthSlider.value = health;
	}
	
	// Update is called once per frame
	void Update ()
	{
		RotateBase ();
	}

	#endregion // UNITY_REGION

	#region PRIVATE_METHODS

	private void RotateBase ()
	{
		if ( mIsAlive && gameObject != null ) {
			// implement object rotation
			transform.Rotate ( Vector3.up, rotationSpeed * Time.deltaTime);
		}
	}

	// Destroy base
	private IEnumerator DestroyBase ()
	{
		mIsAlive = false;
		mAudioSource.clip = explosionSoundFx;
		mAudioSource.Play ();

		GetComponent<Renderer> ().enabled = false;

		// inform all Enemies that Base is Lost
		GameObject[] enemies = GameObject.FindGameObjectsWithTag ("Enemy");
		foreach (GameObject e in enemies) {
			e.gameObject.GetComponent<EnemyScript> ().SwitchBaseStatus (false);
		}

		yield return new WaitForSeconds (mAudioSource.clip.length);
		Destroy (gameObject);

	}

	#endregion // PRIVATE_METHODS

	#region PUBLIC_METHODS

	// receive damage
	public void TakeHit (int damage)
	{
		health -= damage;

		mHealthSlider.value = health;

		if (health <= 0) {
			StartCoroutine (DestroyBase ());
		} else {
			mAudioSource.clip = hitSoundFx;
			mAudioSource.Play ();
		}
	}

	#endregion // PUBLIC_METHODS
}

Now we need to add and configure the script.

Select the Base in the hierarchy, click on Add Component, and add an Audio Source. Now drag MyBase to the Base element and, in the Inspector panel, expand MyBase. Select a sound effect for the explosion and hit. I’ve used the explosion clip used in the last tutorial, but feel free to add your own. Finally, in the Health Slider, select the UISlider element.

Create a Pokémon GO Style Augmented Reality Game With Vuforia: Image Targets

Defending the Base

Our new game experience is almost done. We only need to shoot some lasers to start defending our base. Let’s create a script for the laser!

First drag the _PlayerController from the Prefab folder to the hierarchy. Expand _PlayerController and select _LaserController. In the Inspector panel, find Laser Script and click on Edit.

The only thing that we need to change in this script is the position of the laser.

// Shot the Laser
    private void Fire ()
	{
		// Get ARCamera Transform
		Transform cam = Camera.main.transform;

		// Define the time of the next fire
		mNextFire = Time.time + mFireRate;

		// Set the origin of the RayCast
		Vector3 rayOrigin = cam.position;

		// Show the Laser using a Coroutine
		StartCoroutine (LaserFx ());

		// Holds the Hit information
		RaycastHit hit;

		// Set the origin position of the Laser Line
		// It will add 10 units down from the ARCamera
		// We adopted this logic for simplicity
		Vector3 laserStartPos = new Vector3 (cam.position.x, cam.position.y -2f, cam.position.z);
		mLaserLine.SetPosition (0, laserStartPos);	

		// Checks if the RayCast hit something
		if (Physics.Raycast (rayOrigin, cam.forward, out hit, mFireRange)) {

			// Set the end of the Laser Line to the object hit
			mLaserLine.SetPosition (1, hit.point);

			// check target type
			if (hit.collider.tag == "Enemy") {

				CubeBehaviorScript cubeCtr = hit.collider.GetComponent<CubeBehaviorScript> ();
				if (cubeCtr != null) {
					if (hit.rigidbody != null) {
						hit.rigidbody.AddForce (-hit.normal * mHitForce);
						cubeCtr.Hit (mLaserDamage);
					}
				}
			}

		} else {
			// Set the enfo of the laser line to be forward the camera
			// using the Laser range
			mLaserLine.SetPosition (1, cam.forward * mFireRange);
		}
	}

Trying Out the Game

That was a lot of work, but now it’s time to play the game! Print out the target image and try to run your game on your phone or tablet. Have some fun with it and see if you can come up with some ways to improve the game!

At this point, you have a good understanding of how the Vuforia system works and how to use it with Unity. I expect that you’ve enjoyed this journey as much as I have. See you soon!

To learn more about Augmented Reality with Vuforia and Unity, check out our video course here on СodeHolder Tuts+!

  • Create a Pokémon GO Style Augmented Reality Game With Vuforia: Image Targets
    Mobile App
    Pokémon GO Style Augmented Reality: Markers
    Derek Jensen