Code implementation details

Obviously, the most important part of any project is actually to implement what we want to accomplish. We want this project to play a literary quote from a list of audio samples automatically. To do this, we need an audio source and audio clips. We also want this project to take advantage of ARKit to run, so we need to write a C# class that utilizes features from the ARKit plugin that is exposed from the Objective-C and C++ libraries.

Let’s open up the ARHitCube class, fill in the details, and explain what is happening at the same time. I should note that very similar code is already provided in the script file called UnityARHitTestExample; I created this script to be able to show only what is needed and to be able to explain the workflow/thoughts necessary for creating the functionality we need:

using System;
using System.Collections.Generic;
  1. As per usual, we will only call the specific namespaces we need for our project. In this case, it is System and System.Collections.Generic:
namespace UnityEngine.XR.iOS
  1. Our namespace will be used to organize our code to make sure it stays separate from ARKit and Unity’s API, which will avoid naming collisions:
public class UnityARHitTestExample : MonoBehaviour
{
public Transform m_HitTransform;
public AudioClip[] clips;
public AudioSource source;
  1. Our class will inherit from MonoBehavior, as we want to be able to use it directly from the object (as well as make sure it can be attached to the game object).
  2. We create a public transform to allow us to track locations and a public array of audio clips more easily:
bool HitTestWithResultType (ARPoint point, ARHitTestResultType resultTypes)
{
List hitResults = UnityARSessionNativeInterface.GetARSessionNativeInterface ().HitTest (point, resultTypes);

  1. We create a Boolean method type that has the parameters of ARPoint and ARHitTestResultType. Both of these are exposed by ARKit, and you can read the documentation for them or look at the source in Unity to gain a better understanding of it. The simplified explanation is that ARPoint is a point coordinate derived from a Vector 3 value, and ARHitTestResultType is an enum with the possible results being ARHitTestResultTypeFeaturePoint, ARHitTestResultTypeEstimatedHorizontalPlaneARHitTestResultTypeEstimatedVerticalPlaneARHitTestResultTypeExistingPlaneARHitTestResultTypeExistingPlaneUsingExtent, and ARHitTestResultTypeExistingPlaneUsingGeometry.
  2. We create a list called hitResults which is going to be set to be UnityARSessionNativeInterface. GetARSessionNativeInterface().HitTest with the parameters being point and result types filled in. What this does is create a list every time a native interface hit test is registered and stores the values:
if (hitResults.Count > 0) {
foreach (var hitResult in hitResults) {
Debug.Log ("Got hit!");
m_HitTransform.position = UnityARMatrixOps.GetPosition (hitResult.worldTransform);
m_HitTransform.rotation = UnityARMatrixOps.GetRotation (hitResult.worldTransform);
return true;
}
}
return false;
}
  1. Next up, we do an if check to verify that the count is greater than 0. If it isn’t greater than 0, return as false, otherwise proceed to the foreach loop. Inside of the foreach loop, we check all of the hit results and log the results. The HitTransform position will always be set to be UnityARMatrixOps.GetPosition with the parameter being the hitresult.worldTransform.
  2. The HitTransform rotation will also always be set to be UnityARMatrixOps.GetRotation with the parameter being the hitresult.worldtransform. We end by returning true. Essentially, all this function does is detect whether a hit is registered or not and passes information to the correct areas that need the information:
void Update () {
/* Let’s start the update method as it is probably the second most important aspect of the code.
*/
if (Input.touchCount > 0 && m_HitTransform != null)
{
var touch = Input.GetTouch(0);
  1. The first thing we want to do is check whether or not the input.touchcount is 0 and the HitTransform is not equal to null. If either of these checks fails, then we aren’t going to be able to retrieve the information we need.
  2. We set a touch variable to be input.gettouch with the parameter being 0. 0 is the basic tap gesture:
if (touch.phase == TouchPhase.Began)
{
var screenPosition = Camera.main.ScreenToViewportPoint(touch.position);
  1. The if touch phase statement here is a check to see which touch phase is being initialized. The began touch phase is what we want, as it is the starting location of touch events.
  2. We created a screen position variable and set it to be the camera screen to viewport point, with the parameter filled out being the touch position:
ARPoint point = new ARPoint 
{
x = screenPosition.x,
y = screenPosition.y
};
  1. ARPoint point is set to be a new ARPoint, and we want the x value to be the screen position’s x value and the y value to be the screen position’s y value:
ARHitTestResultType[] resultTypes = {
ARHitTestResultType.ARHitTestResultTypeExistingPlaneUsingExtent,
ARHitTestResultType.ARHitTestResultTypeHorizontalPlane,
ARHitTestResultType.ARHitTestResultTypeFeaturePoint
};
  1. ARHitTestResultType is an array called result types. We want to make sure that the hit test result types are understood, and in this case, we have three types to use: ExistingPlaneUsingExtent, HorizontalPlane, and FeaturePoint:
foreach (ARHitTestResultType resultType in resultTypes)
if (HitTestWithResultType (point, resultType))
{
source.PlayOneShot(clips[Random.Range(0, clips.Length)]);
source.Stop();
return;
}
  1. We can now do a final foreach loop on the ARHitTestResultType and create an if statement to check the HitTestWithResultType with the parameters filled with the point and resultType. This essentially just checks to see if the proper touch events have occurred, and if they have, then it activates the play method. Upon another touch event, it will stop the media that was playing. Following that, we return to break from the loop.
  2. We can go back to the Unity Editor and look at the cube object's attached script:

  1. We can attach our Cube to be the Hit Transform as when we tap, this will be the registered object to read the information:

We can now build this project:

  1. To do this, click on File and Build Settings. We will be utilizing iOS as the platform:
  1. In Player Settings, we need to change our app’s name in the Bundle Identifier area and write a small description in the camera usage description.
  2. I will name the app com.rpstudios.arkitscene, and the description will be AR BABY:
  1. Once we select Build app, Unity will create an XCode project, which is the main difference between building for Android, Windows, and Linux:

The main bulk of the work is done; now we just need to get familiar with XCode and finalize the build process there.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.17.154.171