Explore the HelloAR Sample App Code

Dive into the ARCore SDK for Unity sample app code to learn how SDK components work in an AR scene.

Prerequisites

This guide assumes that you have downloaded and installed the ARCore SDK for Unity. If you are new to the SDK, see the ARCore SDK for Unity quickstart guide first.

Tour the sample app

Take a look at the SDK components in the HelloAR sample scene.

  1. In the Unity Project window, navigate to Assets > Examples > HelloAR > Scenes > HelloAR.

  2. Double-click the HelloAR scene to open it.

  3. Use the Hierarchy window to start navigating the sample scene. You'll find the following ARCore game objects:

    Game Object Description
    ARCore Device Prefab that manages the ARCore session.

    Holds the First Person Camera game object, which uses the camera on the back of your device to capture real world images and make them available as the background of the AR scene.
    Environmental Light Prefab that adjusts lighting in the AR scene using an estimate of the average pixel brightness in the image that your camera captures. To do this, in each frame:
    Point Cloud Prefab for feature points detected in the current frame.
    Example Controller Game object whose controller script manages the AR scene.
    The controller script has references to the following game objects:
    • First Person Camera
    • Prefabs for dynamically creating game objects:
      • Detected Plane: Prefab for visualizing detected planes.
      • Andy Android: Prefab that users can place in the AR scene.
      • Searching for Plane: UI text element shown during plane detection.

    See the following section to step through the Example Controller code.

Explore the code

Now that you have an idea of the main ARCore game objects in the sample scene, step through the code that makes them work together.

The ExampleController script implements the critical aspects of the ARCore sample app experience.

Access the code

  1. In the HelloAR scene, click the Example Controller game object.

  2. In the Inspector window, double-click the HelloARController script to open it in your editor.

Step through the code

Take a look at the code. In the HelloARController script, the Update() method handles critical tasks in each frame:

Check for motion tracking

  • Motion tracking provides plane detection. The Update() method calls the _UpdateApplicationLifecycle() method to check motion tracking. The following code is in _UpdateApplicationLifecycle():
  // Check that motion tracking is tracking.
  if (Session.Status != SessionStatus.Tracking)
  {
      const int lostTrackingSleepTimeout = 15;
      Screen.sleepTimeout = lostTrackingSleepTimeout;
      if (!m_IsQuitting && Session.Status.IsValid())
      {
          SearchingForPlaneUI.SetActive(true);
      }

      return;
  }

Detect new and existing planes in the real world scene

  • ARCore looks for new planes to track in the real world scene.

  • The "Seaching for Planes" UI text element is shown as long as new and existing planes are not yet detected. Once at least one plane is being tracked, the text element is hidden.

 // Hide snackbar when currently tracking at least one plane.
    Session.GetTrackables<DetectedPlane>(m_AllPlanes);
            bool showSearchingUI = true;
            for (int i = 0; i < m_AllPlanes.Count; i++)
            {
                if (m_AllPlanes[i].TrackingState == TrackingState.Tracking)
                {
                    showSearchingUI = false;
                    break;
                }
            }

            SearchingForPlaneUI.SetActive(showSearchingUI);

Process user input for placing virtual objects

After planes are tracked, the Update() method handles user input for placing Andy Android objects on the planes.

  • When a user taps the screen, Frame.Raycast() uses a raycast from the tap position to detect whether the user tapped a plane or oriented points.

  • If the user taps a plane or a surface of oriented points, then an Andy Android object is instantiated at the TrackableHit pose where the user tapped.

  • The hit pose is used to create an Anchor.

    • The anchor keeps the Andy game object in the same position relative to the real world.
    • When you no longer need an anchor, call Unity's GameObject Destroy() method on it. This signals ARCore to stop tracking the anchor.
  • The camera position is used to adjust the Andy object's transform so that Andy appears to look at the camera from his position.

  • The Andy object's transform inherits the hit's anchor so that the Andy object stays where the user placed it as the user moves their phone around.

   // Raycast against the location the player touched to search for planes.
            TrackableHit hit;
            TrackableHitFlags raycastFilter = TrackableHitFlags.PlaneWithinPolygon |
                TrackableHitFlags.FeaturePointWithSurfaceNormal;

            if (Frame.Raycast(touch.position.x, touch.position.y, raycastFilter, out hit))
            {
                // Use hit pose and camera pose to check if hittest is from the
                // back of the plane, if it is, no need to create the anchor.
                if ((hit.Trackable is DetectedPlane) &&
                    Vector3.Dot(FirstPersonCamera.transform.position - hit.Pose.position,
                        hit.Pose.rotation * Vector3.up) < 0)
                {
                    Debug.Log("Hit at back of the current DetectedPlane");
                }
                else
                {
                    // Instantiate Andy model at the hit pose.
                    var andyObject = Instantiate(AndyAndroidPrefab, hit.Pose.position, hit.Pose.rotation);

                    // Compensate for the hitPose rotation facing away from the raycast (i.e. camera).
                    andyObject.transform.Rotate(0, k_ModelRotation, 0, Space.Self);

                    // Create an anchor to allow ARCore to track the hitpoint as understanding of the physical
                    // world evolves.
                    var anchor = hit.Trackable.CreateAnchor(hit.Pose);

                    // Make Andy model a child of the anchor.
                    andyObject.transform.parent = anchor.transform;
                }
            }

Send feedback about...