Your First ARMOD Project

Description

This article will introduce the Focus SLAM mode to realize the AR experience of IKEA Place furniture placement.
Focus SLAM is a focused SLAM algorithm, which places the AR virtual body on the position of the indicator.

Prepartion

The following software and development kits must be installed before starting to create an AR experience:
Software:
  • Unity 2020.3
  • iTunes (for iPhone Debug)
Development Kit:
  • ARMOD Package Tools
  • ARMOD Render Assistant
  • ARMOD API
  • ARMOD Simulator
  • ARMOD Debugger
  • ARFoundation (ARKit/ARCore/ARKit FaceTracking)

How to getting the Development kit?

You can read this article to install it!

How to create an unity project?

You can read this article to create it!

Create An ARMOD Project

Through the previous preparations, we have installed all the necessary development kits, and we can use PacakgeTools to assist us in creating a project.

Project directory

Before starting to create, you need to understand the AR-MOD project directory structure. When we use PackageTools to create the structure as follows:
1
FocusExample
2
├─Artwork
3
├─AutomaticGenerated
4
├─Configures
5
└─Scripts
6
├─Editor
7
└─Runtime
Copied!
Name
Description
FocusExample
The project name of the AR-MOD project
Artwork
Store and manage art resources, you can create sub-folders for classified management
AutomaticGenerated
When building the package body, such as MOD dll, AR feature configuration files, etc. are automatically generated, which is a necessary configuration
Configures
It is automatically created when the project is created, and is used to cache the configuration of AR features. After the project is created, it cannot be deleted, otherwise an error will occur
Scripts
All the code storage location of the project
Editor
Only used in the Unity Editor, generally stores auxiliary resource scripts such as the quick configuration panel of the project, and does not participate in runtime construction
Runtime
Store the runtime code of the AR project, you can create more scripts to implement more interesting logic
AR-MOD will not automatically load the resources in the AR experience package, so it needs to be loaded by the script itself

AR Virutal Content

3D Focus Sign

Right-click on the Unity Hierarchy panel to create an empty GameObject and rename it to FocusGroup and create two child GameObjects (Quad) for it, name them Found and Finding respectively, and set the Rotation X of these two GameObjects to 90°.[1]
Create 3D Focus Sign
Find the corresponding project Artwork folder in the Assets panel, create a new folder named Materials, create two shaders in the Materials folder named Focus_Finding_Mat and Focus_Found_Mat; and give the two Quad GameObjects created by [1].
Crreate Materials for 3D Focus Sign
Set the textures of Focus_Finding_Mat and Focus_Found_Mat to distinguish the two states.
State
Texture
Finding
Found
Set the Active of Focus_Finding and Focus_Found in the Inspector to False to hide the display.
Found State Active state
Finding State Active state
Drag and drop from Hierarchy to Assets and save as Prefab
Make 3D Focus Sign To A Prefab

User Interface

Create a UICanvas in the Unity Hierarchy panel as shown below:
Create A Canvas To Draw UI
Set its screen adaptive
Adaptive
Create a UI to prompt the user to move the phone and Place button, etc.
Drag and drop EventSystem into Canvas to make it a child object
Make UICanvas to prefab

AR Object

Right-click in the Unity Hierarchy panel to create an empty GameObject and rename it to ARObject. Drag and drop the model to be placed inside the ARObject to make it a sub-object
Make ARObject to a prefab

Features

By enabling PackageTools -> Property window, right-click the blank space to add Block. It can be configured according to the following figure:

Include AR Object

By enabling the PackageTools -> Contents window, by dragging the assets in the Assets panel to the Contents panel. Drag and drop the Prefabs we just made into the Contents window
  • Contents panel only accepts files recognized by Unity
  • No need to drag the resources of the AutomaticGenerated folder into Contents
  • Just drag the Artwork resource into the Contents panel
Id
Description
Light Yellow
Asset Name is used for the name (index) when the runtime script loads the resource
Light Pink
Asset Path records the location of the current resource in the project
Light Cyan
All the resources in the AR experience content pack will be listed here.

Interaction Logic

When we create the project, PackageTools will automatically create the corresponding logic script for us; the name of the file is the Project name + MainEntry.cs. Go to the FocusExample/Script/Runtime/ directory to find the FocusExampleMainEntry.cs file and double-click to open it. You can see the following code:
1
using UnityEngine;
2
using System;
3
using System.Collections;
4
using com.Phantoms.ActionNotification.Runtime;
5
6
namespace FocusExample
7
{
8
public class FocusExampleMainEntry
9
{
10
//Please delete the function if it is not used
11
public void OnLoad()
12
{
13
//Use this for initialization
14
}
15
16
//Please delete the function if it is not used
17
public void OnEvent(BaseNotificationData _data)
18
{
19
//General event callback
20
}
21
22
//Please delete the function if it is not used
23
public void OnUpdate()
24
{
25
//Update
26
}
27
28
//Please delete the function if it is not used
29
public void ReleaseMemory()
30
{
31
//Release Memory after AR close
32
}
33
}
34
}
Copied!
Before we start to write the code for AR interaction logic. At first, we need to understand the functional life cycle of ARMOD. As shown below:
life cycle of ARMOD
After we figure out the life cycle of the ARMOD function, we can start writing code. At the first, we need to load our UI, Focus Group, AR Object and other resources in the OnLoad function.
Term
Description
UI
That is, the User Interface is called the user interface in Chinese, and the user interaction interface attached to the screen. Such as buttons, text, pictures, etc.
Focus Group
The focus group (GameObject) is used to remind the user that the area currently viewed allows the placement of the AR virtual body. It is called a group because it contains two states: 1. Find the state; 2. Find the state;
AR Object
Virtual objects to be superimposed with reality, such as 3D models, videos, images, voices, etc.
When loading the resources in the AR experience package, we can load the resources through the ARMOD API. For details, please refer to the ARMOD API.
1
private API api = new API();
2
private const string CONST_PROJECT_NAME = "FocusExample";
3
private const string CONST_AR_OBJECT = "Chair";
4
private const string CONST_UI_CANVAS = "Canvas";
5
private const string CONST_FOCUS_GROUP = "FocusGroup";
6
7
private GameObject arObject;
8
private GameObject uiCanvas;
9
private GameObject FocusGroup;
10
11
//Please delete the function if it is not used
12
public void OnLoad()
13
{
14
api.LoadGameObject(CONST_PROJECT_NAME,
15
CONST_UI_CANVAS,
16
_result => { uiCanvas = api.InstanceGameObject(_result, "", null); });
17
18
api.LoadGameObject(CONST_PROJECT_NAME,
19
CONST_FOCUS_GROUP,
20
_result => { FocusGroup = api.InstanceGameObject(_result, "", null); });
21
22
api.LoadGameObject(CONST_PROJECT_NAME,
23
CONST_AR_OBJECT,
24
_result => { arObject = api.InstanceGameObject(_result, "", null); });
25
}
Copied!
  • We need to write the variables that need to be called in different {} outside {} and define them as member variables
  • api.LoadGameObject only loads the preset body (memory index) from the AR experience package and will not be instantiated and displayed in the scene. Therefore, you need to call InstanceGameObject to host and instantiate it into the scene. You can also use Instantiate in Unity!
  • There are certain differences between Instantiate and api.InstanceGameObject. InstanceGameObject in ARMOD will automatically host all instantiated resources, while Instantiate in Unity will not automatically host and need to be managed by itself. If the AR function module is closed, the InstanceGameObject in ARMOD will release the resources.
After all the required resources are loaded, we need to perform the feedback logic processing of the current AR algorithm. Based on user operation feedback, such as the current position can be placed in the AR virtual body or the AR virtual object is not allowed to be placed in the corresponding sensory feedback; at this moment we need to use Focus Group And the two status indicator Finding and Found managed by it. When the FindingType is in the Finding state, we need to set the Finding state indicator inFocus Group to the active rendering state, and the Found state indicator to the inactive non-rendering state; when it is in the Found state, the opposite is true.
Focus Group has two state( Finding and Found) are GameObjects, so we need to find these GameObjects first when setting their states and rendering. We search and acquire in the corresponding loaded resource callback. The following code:
1
api.LoadGameObject(CONST_PROJECT_NAME,CONST_FOCUS_GROUP,
2
_result =>
3
{
4
focusGroup = api.InstanceGameObject(_result, "", null);
5
//Addition Lines
6
focusFinding = api.FindGameObjectByName(CONST_FOCUS_FINDING);
7
focusFound = api.FindGameObjectByName(CONST_FOCUS_FOUND);
8
focusGroupTrans = focusGroup.transform;
9
});
Copied!
api.FindGameObjectByName can find GameObject objects that are not activated
After the status indicator is loaded, we need to further prompt based on user operations. When the status is Found, the button of the AR virtual object should be placed on the screen, and the button is hidden when the status is Finding; when the user clicks the button, the AR virtual object can be placed in the position of the Found indicator. But at this time, we have only loaded the corresponding UI Canvas and have not obtained the corresponding button, and we need to set the click feedback event for the button. Load the button in the same way as the two states of the Focus Group.
1
api.LoadGameObject(CONST_PROJECT_NAME,CONST_UI_CANVAS,
2
_result =>
3
{
4
uiCanvas = api.InstanceGameObject(_result, "", null);
5
6
//Addition Lines
7
placeButtonGameObject = api.FindGameObjectByName(CONST_PLACE_BUTTON);
8
placeButton = placeButtonGameObject.GetComponent<Button>();
9
uiTips = api.FindGameObjectByName(CONST_UI_TIPS);
10
11
uiTips.SetActive(true);
12
13
//Button Event
14
placeButton.onClick.AddListener(() =>
15
{
16
arObject.SetActive(true);
17
arObject.transform.position = worldPosition;
18
arObject.transform.rotation = worldRotation;
19
focusGroup.SetActive(false);
20
uiTips.SetActive(false);
21
22
//Only once
23
placeButtonGameObject.SetActive(false);
24
placed = true;
25
});
26
});
Copied!
Use the OnEvent event function to control the status of the Focus Group and set the position and angle of the Focus Group. Code show as below:
1
//Please delete the function if it is not used
2
public void OnEvent(BaseNotificationData _data)
3
{
4
if (placed) return;
5
if(focusGroup==null)return;
6
if(focusFinding==null)return;
7
if(focusFound==null)return;
8
if(placeButtonGameObject==null)return;
9
10
if (_data is FocusResultNotificationData _FocusResult)
11
{
12
switch (_FocusResult.FocusState)
13
{
14
case FindingType.Finding:
15
focusGroup.SetActive(true);
16
focusFound.SetActive(false);
17
focusFinding.SetActive(true);
18
placeButtonGameObject.SetActive(false);
19
break;
20
case FindingType.Found:
21
focusGroup.SetActive(true);
22
focusFound.SetActive(true);
23
focusFinding.SetActive(false);
24
placeButtonGameObject.SetActive(true);
25
break;
26
case FindingType.Limit:
27
focusGroup.SetActive(false);
28
break;
29
}
30
31
worldPosition = _FocusResult.FocusPos;
32
worldRotation = _FocusResult.FocusRot;
33
34
//Move Focus Group
35
focusGroupTrans.position = worldPosition;
36
focusGroupTrans.rotation = worldRotation;
37
}
38
}
Copied!
The complete logic code is as follows:
1
using UnityEngine;
2
using System;
3
using System.Collections;
4
using com.Phantoms.ActionNotification.Runtime;
5
using com.Phantoms.ARMODAPI.Runtime;
6
using UnityEngine.UI;
7
using Object = UnityEngine.Object;
8
9
namespace FocusExample
10
{
11
public class FocusExampleMainEntry
12
{
13
private API api = new API();
14
private const string CONST_PROJECT_NAME = "FocusExample";
15
private const string CONST_AR_OBJECT = "Chair";
16
private const string CONST_UI_CANVAS = "Canvas";
17
private const string CONST_FOCUS_GROUP = "FocusGroup";
18
private const string CONST_FOCUS_FINDING = "Finding";
19
private const string CONST_FOCUS_FOUND = "Found";
20
private const string CONST_PLACE_BUTTON = "Place";
21
private const string CONST_UI_TIPS = "UITips";
22
23
private GameObject arObject;
24
private GameObject uiCanvas;
25
private GameObject focusGroup;
26
27
28
private GameObject focusFinding;
29
private GameObject focusFound;
30
private GameObject placeButtonGameObject;
31
private GameObject uiTips;
32
private Transform focusGroupTrans;
33
34
private Button placeButton;
35
36
private Vector3 worldPosition;
37
private Quaternion worldRotation;
38
39
private bool placed;
40
41
//Please delete the function if it is not used
42
public void OnLoad()
43
{
44
api.LoadGameObject(CONST_PROJECT_NAME,
45
CONST_UI_CANVAS,
46
_result =>
47
{
48
uiCanvas = api.InstanceGameObject(_result, "", null);
49
50
//Addition Lines
51
placeButtonGameObject = api.FindGameObjectByName(CONST_PLACE_BUTTON);
52
placeButton = placeButtonGameObject.GetComponent<Button>();
53
uiTips = api.FindGameObjectByName(CONST_UI_TIPS);
54
55
uiTips.SetActive(true);
56
57
//Button Event
58
placeButton.onClick.AddListener(() =>
59
{
60
arObject.SetActive(true);
61
arObject.transform.position = worldPosition;
62
arObject.transform.rotation = worldRotation;
63
focusGroup.SetActive(false);
64
uiTips.SetActive(false);
65
66
//Only once
67
placeButtonGameObject.SetActive(false);
68
placed = true;
69
});
70
});
71
72
api.LoadGameObject(CONST_PROJECT_NAME,
73
CONST_FOCUS_GROUP,
74
_result =>
75
{
76
focusGroup = api.InstanceGameObject(_result, "", null);
77
focusFinding = api.FindGameObjectByName(CONST_FOCUS_FINDING);
78
focusFound = api.FindGameObjectByName(CONST_FOCUS_FOUND);
79
focusGroupTrans = focusGroup.transform;
80
});
81
82
api.LoadGameObject(CONST_PROJECT_NAME,
83
CONST_AR_OBJECT,
84
_result => { arObject = api.InstanceGameObject(_result, "", null); });
85
}
86
87
//Please delete the function if it is not used
88
public void OnEvent(BaseNotificationData _data)
89
{
90
if (placed) return;
91
if (focusGroup == null) return;
92
if (focusFinding == null) return;
93
if (focusFound == null) return;
94
if (placeButtonGameObject == null) return;
95
96
if (_data is FocusResultNotificationData _FocusResult)
97
{
98
switch (_FocusResult.FocusState)
99
{
100
case FindingType.Finding:
101
focusGroup.SetActive(true);
102
focusFound.SetActive(false);
103
focusFinding.SetActive(true);
104
placeButtonGameObject.SetActive(false);
105
break;
106
case FindingType.Found:
107
focusGroup.SetActive(true);
108
focusFound.SetActive(true);
109
focusFinding.SetActive(false);
110
placeButtonGameObject.SetActive(true);
111
break;
112
case FindingType.Limit:
113
focusGroup.SetActive(false);
114
break;
115
}
116
117
worldPosition = _FocusResult.FocusPos;
118
worldRotation = _FocusResult.FocusRot;
119
120
//Move Focus Group
121
focusGroupTrans.position = worldPosition;
122
focusGroupTrans.rotation = worldRotation;
123
}
124
}
125
}
126
}
Copied!

Build ARExperience

Through this configuration, the AR experience package will be compressed by the corresponding platform. By clickingBuild your own ARExperiences. PackageTools will automatically build the AR experience package.
Build Platform and Platform Group must be consistent
Show in file browser button can go to the AR experience package directory just built

Deploy

Read the Dashboard article
Last modified 6mo ago