Building AR game with AR Foundation in Unity

Updated on Sep. 2019 – Updating examples to AR Foundation 2.0+

I ❤️ Unity for what they are doing for the game industry. With the introduction of ARKit for iOS and ARCode for Android, it was just a matter of time when Unity would unify both technologies under one thing. And I was right!

Introducing AR Foundation in Unity! 🥳

On last GDC they presented a great demo of what AR is currently capable of. And if you are hyped about this tech as I am, you might ask how you can build that?

In the beginning, I was a little bit skeptical if it will work as it’s still in preview, but with building my little project, I found out that it’s much simpler than anything else! 🤓

Packages

If you are not familiar with Unity’s Package Manager, then it’s simply place where Unity distributes all of their packages that you can activate or remove from a project. You can find there a lot of nice plugins, but today we are going to focus only on a few of them.

Here you can find package manager.

To make our project AR-ready, we need to add these packages:

  • ARFoundation – the core of AR.
  • ARKit – if you want to deploy for iOS.
  • ARCore – if you want to deploy for Android.
Here they are!

Scene setup

With these, we will have new components available in Unity editor.
Now we will need to configure our Scene to work with AR.

1. We need AR Session component placed on Scene.

2. We need AR Session Origin somewhere on Scene as well.

3. Add device camera feed to our in-game camera.

Camera Game Object with AR components

If you want to see what surfaces are detected by the device, we can also use Point Cloud to display particles on them.

Creating AR Point Cloud

Unity can also generate a surface mesh by using AR Plane [name].

Creating AR Plane prefab

You should make prefabs from both AR Point Cloud and AR Plane.

Now we need to attach a few more components to our AR Session Origin to use point cloud and surface mesh.

AR Session Origin Object

Make a build

Before we can make a working build we need to change a few options in the project. I’m going to present how you should do it for iOS, but there should be similarities for Android.

1. Check ARKit required and change the minimum iOS version to at least iOS 11.0

Check ARKit and set minimum version to 11.0

2. Fill Message box for Camera Usage

Add Camera Usage Description

3. Change architecture for ARM64

Change architecture

Now we can build a project and see if the device can detect surfaces.

Surface detection on device

If we did everything right then, it should work without a problem.

Let’s add something new!

Our next step will be to place and move a virtual object around in real life.
The first thing we need to do is to find or create that object. I’ll use one of the assets that were made by Kenney.

Our AR space ship

Next step will be to create a script that will place and move our virtual object. It is very similar to what we would have to do if you would like to do it only in a game.

There is just one difference. If you would like to move objects around in a game, we would have to use Physics raycasting. In the AR world, we need to do the same thing, but we are using ARRaycastManager to make those raycasts!

So this is a little example of placing and moving our object.

Updated on Sep. 2019 – you have to add ARRaycastManager to the ARSessionOrgin in order to make it work!

using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.XR.ARFoundation;

/// <summary>
/// This is class responsible for moving game object around in real world.
/// </summary>
public class ARObjectPlacer : MonoBehaviour
{
    // Reference to object prefab
    [SerializeField]
    private GameObject arPrefab;

    // Reference to an instance of the object that will be moved.
    private GameObject arInstance;

    // Reference to Raycast Manager used to make raycasts to detect surfaces.
    private ARRaycastManager arRaycaster;

    // Flag if an object was placed or it should be moved
    private bool objectPlaced = false;

    /// <summary>
    /// Unity method called in before first frame.
    /// </summary>
    void Start()
    {
        // Get reference to AR Raycast Manager within this game object
        arRaycaster = GetComponent<ARRaycastManager>();

        // Create instance of our object and hide it until it won't be placed
        arInstance = Instantiate(arPrefab);
        arInstance.gameObject.SetActive(false);
    }

    /// <summary>
    /// Unity method called every frame.
    /// </summary>
    void Update()
    {
        // If instance is placed then skip update.
        if (objectPlaced)
            return;

        // Make a list of AR hits
        List<ARRaycastHit> hits = new List<ARRaycastHit>();

        // Center point of screen with 4 units of depth what will be used to make raycast
        var screenPoint = new Vector3(Screen.width / 2.0f, Screen.height / 2.0f, 4);

        // Trying to find a sufrace in world.
        if (arRaycaster.Raycast(screenPoint, hits))
        {
            // If we did hit something then we should place the instance in that point in space.

            // Order hits to find closest one.
            hits.OrderBy(h => h.distance);
            var pose = hits[0].pose;

            // Activate instance and move it to position on detected surface
            arInstance.gameObject.SetActive(true);
            arInstance.transform.position = pose.position;
            arInstance.transform.up = pose.up;
        }
        else
        {
            // If we didn't hit anything than we should hide instance
            arInstance.gameObject.SetActive(false);
        }
    }

    /// <summary>
    /// Method used to disable object movement, called by Place Button.
    /// </summary>
    public void PlacingFinished()
    {
        objectPlaced = true;
    }

    /// <summary>
    /// Method used to enable object movement, called by Move Button.
    /// </summary>
    public void PlacingBegin()
    {
        objectPlaced = false;
    }
}

See? As I said, I ❤️ Unity for that. They are making our life so easy these days! 🤓

The result should look like on a gif below.

If you want to see this project yourself, it’s available in my public repository here. 🔗

If you found this interesting or it helped you, share it!
This will help me grow an audience here. 😊

See you next time!

avatar
  Subscribe  
Notify of