Creating an Object Examination App in AR (Part 1/2): Basic Functionalities
In the previous blog posts, we created a plane tracking app that allowed us to place some assets on the plane. In today’s blog post, let’s create another simple app that lets us examine placed objects up close.
Adding an object placing feature
First, we need to create a feature that allows us to track planes and place objects on those planes. Fortunately, we already created this feature for our first app. However, one thing that I would do differently for this app is that we don’t need a parent component for the cube prefab, and we will handle the cube offset through code.
Adding the object examining feature
Brainstorming
Once we’re finished with the object placing feature, let’s add the object examining feature. The idea of this feature is to have an empty object called the examine target. When an object is selected, it will be moved to the position of the examine target; when it’s unselected, it will be moved back to its original position. To position the examine target up close to the phone screen, it needs to be a child of the main camera. This setup will make it follow the camera and create the illusion that it’s attached to the phone screen. Additionally, we will need another empty object that acts as a manager to control the whole process.
Here are all the steps for this feature:
Step 1: Create a child object of the main camera called "examine target".
Step 2: Create a manager script that includes methods to examine and unexamine
objects.
Step 3: Create a script for the examinable (cube) that invokes the methods in
the manager script.
Step 4: Connect the methods in the examinable script to the selection event. Execution
Step 1: Creating an examine target
To create a child object, you can right-click the Main Camera object in the Hierarchy window and select Create Empty.
I want to move this new object’s position on the z-axis 0.35 units further so it’s not too close to the main camera.
Step 2: Creating a manager script
In the Hierarchy window, create an empty GameObject named “Examinable Manager” and create a script for it with the same name. In this script, we first need to get a reference to the examine target. Also, we need to declare some variables to store the object that is being examined, along with its original position and rotation.
[SerializeField] private Transform _examineTarget;
private Vector3 _cachedPos;
private Quaternion _cachedRot;
private Examinable _currentExaminedObj;I serialized the _examineTarget variable so we can reference it in the editor.
Next, we need to create two methods to examine and unexamine an object, which I will call PerformExamine and PerformUnexamine.
public void PerformExamine(Examinable examinable)
{
_currentExaminedObj = examinable;
_cachedPos = _currentExaminedObj.transform.localPosition;
_cachedRot = _currentExaminedObj.transform.localRotation;
_cachedParent = _currentExaminedObj.transform.parent;
_currentExaminedObj.transform.position = _examineTarget.position;
_currentExaminedObj.transform.parent = _examineTarget;
}
public void PerformUnexamine()
{
_currentExaminedObj.transform.parent = _cachedParent;
_currentExaminedObj.transform.localPosition = _cachedPos;
_currentExaminedObj.transform.localRotation = _cachedRot;
}The PerformExamine method accepts our cube prefab (examinable) as its parameter. It then stores that cube prefab in the _currentExaminedObj variable, caches the local position and rotation values of that cube (local position/rotation considers the parent transform compared to position/rotation), caches the parent of the prefab, moves the examined object (_currentExaminedObj) to the position of the examine target, and makes it a child of the examine target.
Get Simon Pham’s stories in your inbox
Join Medium for free to get updates from this writer.
The PerformUnexamine method reverts the examined object’s local position and rotation values back to the cached values and restores its parent.
And here’s the full code for this script:
using UnityEngine;
public class ExaminableManager : MonoBehaviour
{
[SerializeField] private Transform _examineTarget;
private Vector3 _cachedPos;
private Quaternion _cachedRot;
private Transform _cachedParent;
private Examinable _currentExaminedObj;
public void PerformExamine(Examinable examinable)
{
_currentExaminedObj = examinable;
_cachedPos = _currentExaminedObj.transform.localPosition;
_cachedRot = _currentExaminedObj.transform.localRotation;
_cachedParent = _currentExaminedObj.transform.parent;
_currentExaminedObj.transform.position = _examineTarget.position;
_currentExaminedObj.transform.parent = _examineTarget;
}
public void PerformUnexamine()
{
_currentExaminedObj.transform.parent = _cachedParent;
_currentExaminedObj.transform.localPosition = _cachedPos;
_currentExaminedObj.transform.localRotation = _cachedRot;
}
}Step 3: Creating a script for the examinables (cube prefab)
After we’re finished with the manager script, we need to create a script called “Examinable” for the cube prefab. This is where we’re going to call the PerformExamine and PerformUnexamine methods.
In the Examinable script, we first need to get a reference to the Examinable Manager script.
private ExaminableManager _examinableManager;
private void Start()
{
_examinableManager = GameObject.FindObjectOfType<ExaminableManager>();
}The reason why I didn’t serialize it is that the prefab (or examinable object) doesn’t currently exist in the scene, but they will be instantiated at runtime. So, when they are instantiated/enabled, we find the Examinable Manager and get a reference to it.
Additionally, I want to offset the cube by 0.05 units (which is half of the scale on the y-axis) so that they are not halfway in the plane.
private void Start()
{
transform.position = new Vector3(transform.position.x, transform.position.y + 0.05f, transform.position.z);
}Finally, let’s create one function to call the PerformExamine method and another to call the PerformUnexamine method from the manager script.
public void RequestExamine()
{
_examinableManager.PerformExamine(this);
}
public void RequestUnexamine()
{
_examinableManager.PerformUnexamine();
}And here’s the full code for this script:
using UnityEngine;
public class Examinable : MonoBehaviour
{
private ExaminableManager _examinableManager;
private void Start()
{
_examinableManager = GameObject.FindObjectOfType<ExaminableManager>();
transform.position = new Vector3(transform.position.x, transform.position.y + 0.05f, transform.position.z);
}
public void RequestExamine()
{
_examinableManager.PerformExamine(this);
}
public void RequestUnexamine()
{
_examinableManager.PerformUnexamine();
}
}Step 4: Linking the RequestExamine and RequestUnexamine to the selection event.
In Unity, double-click the cube prefab to open it. Let’s add an AR Selection Interactable component and drop the cube collider into the Colliders field, similar to what we did in our first AR app.
Now, expand the Interactable Events list, and under the Select Entered event, create a new slot. Drop in the Examinable script component, and select the RequestExamine function.
Next, do the same for the Select Exited event but select the RequestUnexamine function instead.
Now, these two methods will be called when an object is selected and deselected. We can now test our app.
And it’s working as expected.









