Hello World with Targets (marker)

Here we are going to walk you through all necessary steps to create a native app for Android that makes use of Onirix’s Targets technology. The goal of this tutorial is to create an app that runs on your AR compatible device device and allows us to place AR content on top of an image (functioning as a marker).

Setup and Tools

Let's go over the tools we are going to need.

  1. Onirix Studio the web platform that is the base/starting point for all our AR projects.
  2. Unity is the most popular and widely used 3D engine for mobile applications. Unity is cross-platform, which allows developers to deploy the same app on multiple platforms.
  3. Onirx SDK in its mobile version, allows us to create Targets-type apps.
  4. XCode (only necessary to build iOS apps).

Step 1: Create a new Target Project

We will start by creating a new project in the studio. In this Getting Started video you can see how to create a targets project in Onirix. Inside the project we create a new Surface Target. You have to upload the image that will be used to set 3D content around it.

Yo can find the marker used in the video example here. And you can find the 3D model here.

To get more information about Onirix Studio scene editor visit our Scene editor page.

Step 2: Unity Platform

The next step is to download Unity and create a new project. When opening Unity, a window appears. Make sure you run at least version 2018.2.7.

To create a new project in Unity, go to the projects tab, and click on New project. Give it a name, left all other options by default and create it. It may take several seconds to initialize.

Create project in Unity

Step 3: Onirix SDK

The next step is to download the Onirix SDK. For this we access the Onirix Mobile SDK repository on GitHub and download the latest release (Unity Package), which allows us to create Onirix Targets projects (place virtual content over images or any surface).

A double click on the downloaded package will start the import process to Unity. Unity will show you all the contents of the package. Onirix sdk import screen We leave everything selected and click on Import. This completed the inclusion of the Onirix SDK in our project.

Step 4: Create the App

Now, we have everything we need to create our first app. We will create an empty element inside the scene called MainController (you can name it as you prefer). This element will control the logic of our application.

Now, we will add a series of Scripts in our project. Open the inspector and drag & drop the following scripts inside MainController.

Script 1: OnirixMobileManager

The first one is the OnirixMobileManager. We select the MainController and drag&drop the script.

The OnirixMobileManager component provides us the surface and marker detection. To learn more about OnirixMobileManager visit the SDK documentation.

This script needs some fields (prefabs) to be set from the inspector:

  • Legacy Camera set to LegacyCamera.
  • ARCore Camera set to ARCoreCamera.
  • ARKit Camera set to ARKitCamera.
  • Crosshair Prefab set to Crosshair.
  • Crosshair Found Material set to CrosshairFinding.
  • Crosshair Lost Material set to CrosshairFound.

Although you can provide your own prefabs to the script in order to customize its behaviour and appearance.

After set all the prefabs, it have to look like this:

Onirix Mobile Manager prefabs

Script 2: DynamicLoadManager

The next script that we must include is the DynamicLoadManager. It is responsible for allowing elements to be included dynamically in the execution of our app. To learn more about DynamicLoadManager visit the SDK documentation.

We select the MainController and drag&drop the script.

This script needs only one prefab:

  • Placeholder set to LoadingElement (that is, the element that we will appear while the asset is being loaded).

Dynamic load manager prefabs

Script 3: OnirixAssetLoader

We are not done yet. The next script is the OnirixAssetLoader. It is responsive for get the scene assets from Onirix Studio. To learn more about OnirixAssetLoader visit the SDK documentation.

It is found in dependencies/Onirix SDK/plugins/OnirixCore. We select the MainController and use drag&drop to import script.

This script needs four prefabs to set the default elements that are shown in case there is an error when loading 3D objects, 2D elements, videos or audios:

  • Default 2D Element set to Default2DElement.
  • Default 3D Element set to Default3DElement.
  • Default Video Element set to DefaultVideoElement.
  • Default Audio Element set to DefaultAudioElement.

Dynamic load manager prefabs

Script 4: Our Own Script

Create a new script

We are going to add a script of our own that will be in charge of managing the load logic of the newly created target inside the Studio. We create a Scripts folder and a new Script that we will call MainController. We double click to edit it.

All Unity scripts that extend MonoBehaviour come with two default lifecycle methods: Start (called at the beginning of the script) and Update (called once per frame). In this tutorial we only will need to fill the Start method.

Global variables

Now we are going to create a series of global variables at Script level.

[SerializeField] private string _projectToken;
[SerializeField] private string _projectOid;
[SerializeField] private Text _statusText;

First reference to the project token, which is the ID that allows us to access the Onirix project from the SDK. Second, a reference to the projectOid in Onirix, which is the Oid of the project that contains the targets that we want to use. We will create other reference: a label for messages that will show us the status of the application.

For Text classes to work we must include UnityEngine.UI namespace.

Finally you have to drag&drop the newly created script into the MainController element, and the corresponding placeholders will appear. You can later set values for this serialized fields from script inspector (Set the custom prefabs).

OnirixMobileManager instance

In this step, we are going to create an instance of the OnirixMobileManager. It is in charge of managing everything that has to do with the AR in our app. Also, we are going to create a public getter property to get that reference.

private OnirixMobileManager _onirixMobileManager;

public OnirixMobileManager MobileManager
    {
        get
        {
            if (!_onirixMobileManager)
        {
            _onirixMobileManager = gameObject.GetComponent<OnirixMobileManager>();
        }
        return _onirixMobileManager;
        }
    }

Create the UI

Now it’s time to create our user interface. We create the canvas and we establish some reference resolution to work with, for example, full HD (1920x1080).

We add the status text Status text, and we anchor it in the top position center, for example to -100 pixels of the top anchor. We adjust height and width and center it horizontally. We change the default text to Welcome to Onirix, increase size, etc.

Set the custom prefabs

The first one is the Project token which we will get from the Studio. We access the project view and we get it from the contextual menu of the project, on the copy button. We go back to Unity and paste it in the section.

To get the project Oid we can copy it from the project’s studio url, and paste it into the corresponding placeholder.

Finally we have to set the last MainController prefab with the statusText control.

At this point your MainController inspector tab have to look like this:

Final main controller

Adding Code

Now is time to type some code in own MainController script.

The first thing that we want to change inside the app is preventing the screen from switching to energy saving mode. To achieve this, we use a variable of the Screen class, called sleepTimeout, which allows us to prevent it from ever entering that state. Add this code at the beginning of Start method.

Screen.sleepTimeout = SleepTimeout.NeverSleep;

The next thing is to initialize the DynamicLoadManager, which will load our Target. To do this with our instance we call the Init method and we set the parameters: the MobileManager, the project token and a listener that tells us when an asset has been loaded, when it is loading or downloading. Add this code to Start method.

DynamicLoadManager.Instance.Init(MobileManager, _projectToken, this);

We can use this class as the listener's own implementer. Simply extend this IDynamicLoadListener class and implement its methods. For now we can write the corresponding message within our reference for the StatusText. We define one for each case.

public void OnTargetAssetsDownloaded(Target target)
{
    _statusText.text = "Assets downloaded";
}

public void OnTargetAssetsLoaded(Target target)
{
    _statusText.text = "Assets loaded";
}

public void OnTargetAssetsStartDownloading(Target target)
{
    _statusText.text = "Downloading assets";
}

public void OnTargetAssetsStartLoading(Target target)
{
    _statusText.text = "Loading assets";
}

The next logical step would be to start the surface detection, but since this a feature of ARCore / ARKit, we can not access this feature without initializing the AR framework before. For this we create a coroutine that is waiting until that happens.

We create it in a new method: WaitForAR, and we use the IsReady flag of the MobileManager to know when it is available. When it becomes available, we return the coroutine. We start it inside the Start method and are done.

Add the WaitForAR method to script.

private IEnumerator WaitForAR(System.Action onReady)
{
    yield return new WaitUntil(() => MobileManager.IsReady);
    onReady();
}

And add the coroutine inside the Start method.

StartCoroutine
    (
        WaitForAR
        (
            () =>
            {
                MobileManager.StartDetection(_projectOid, _projectToken,
                    (detectedTarget) =>
                    {
                        MobileManager.HideCrosshair();
                        _statusText.text = "Loading target {detectedTarget}, please wait ...";
                        DynamicLoadManager.Instance.LoadTarget(detectedTarget);
                    }
                );

            }
        )
    );

Once the AR Framework has been started we can begin with the markers detection. We call the StartDetection method of the MobileManager. It receives three params: the project token, the project Oid and one callback. This callback will be executed when one of the projects markers is detected by the Onirix SDK. The callback got one param (detectedMarker) which have the detected marker oid.

Now we have the target oid but we have to load the corresponding asset with the DynamicLoadManager. We go to the loadTarget method, we give the corresponding target Oid.

DynamicLoadManager.Instance.LoadTarget(detectedTarget); 

Before load we update the StatusText indicating which target are going to load.

_statusText.text = "Loading target {detectedTarget}, please wait ...";

We also hide the Crosshair.

MobileManager.HideCrosshair();

Step 5: Exporting the App

Exporting for iOS

Please be sure you have XCode installed before continue.

We only have to build (compile and export) the app. We click on BuildSettings, choose the destination platform (iOS in this case) and click on Switch platform. Don’t worry if It takes a while to import the necessary assets.

Before build the app we need to set a few configurations.

First of them are in Player Settings tab. To reach this tab we can press Player Settings button in Build Settings window or go throw Edit menu Edit/Project Settings/Player). We have to change four configuration properties:

  1. Api Compatibility Level set to .NET 2.0
  2. Requires ARKit support set to checked.
  3. Target minimum iOS Version set to 11.
  4. Allow unsafe code.

Finally we have to go to Graphic settings tab. To reach this tab we have to go throw Edit menu Edit/Project Settings/Player. We have to change a couple of properties in the shader preloading section:

  1. Size set to 1.
  2. Element0 set to OnirixGLTFShaderVariants.

After set this configurations we can press the Build And Run button. After a while XCode will be opened and we will be able to run our new app in a connected iOS device.

Exporting for Android

Please see Hello World with Targets (surface).

Final result