Version 1.2 of the ARCore SDK, as announced at Google I/O 2018, is now available. See the blog post for more information.

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.


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 phone 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:
      • Tracked Plane: Visualizes 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

  // Check that motion tracking is tracking.
  if (Session.Status != SessionStatus.Tracking)
      const int lostTrackingSleepTimeout = 15;
      Screen.sleepTimeout = lostTrackingSleepTimeout;
      if (!m_IsQuitting && Session.Status.IsValid())


Detect new and existing planes in the real world scene

  • ARCore looks for new planes to track in the real world scene. Planes are clusters of feature points that appear to lie on common surfaces.

  • For each discovered plane, a new game object is created to visualize and track that plane.

  • 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.

  // Iterate over planes found in this frame and instantiate corresponding GameObjects to visualize them.
  Session.GetTrackables<TrackedPlane>(m_NewPlanes, TrackableQueryFilter.New);
  for (int i = 0; i < m_NewPlanes.Count; i++)
      // Instantiate a plane visualization prefab and set it to track the new plane. The transform is set to
      // the origin with an identity rotation since the mesh for our prefab is updated in Unity World
      // coordinates.
      GameObject planeObject = Instantiate(TrackedPlanePrefab,, Quaternion.identity,

  // Disable the snackbar UI when no planes are valid.
  bool showSearchingUI = true;
  for (int i = 0; i < m_AllPlanes.Count; i++)
      if (m_AllPlanes[i].TrackingState == TrackingState.Tracking)
          showSearchingUI = false;


Process user input for placing virtual objects

After planes are tracked and visualized, 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 |

  if (Frame.Raycast(touch.position.x, touch.position.y, raycastFilter, out hit))
      var andyObject = Instantiate(AndyAndroidPrefab, hit.Pose.position, hit.Pose.rotation);

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

      // Andy should look at the camera but still be flush with the plane.
      if ((hit.Flags & TrackableHitFlags.PlaneWithinPolygon) != TrackableHitFlags.None)
          // Get the camera position and match the y-component with the hit position.
          Vector3 cameraPositionSameY = FirstPersonCamera.transform.position;
          cameraPositionSameY.y = hit.Pose.position.y;

          // Have Andy look toward the camera respecting his "up" perspective, which may be from ceiling.
          andyObject.transform.LookAt(cameraPositionSameY, andyObject.transform.up);

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

Send feedback about...