Google is committed to advancing racial equity for Black communities. See how.

Instant Placement developer guide for Unity

Learn how to use the Instant Placement API in your own apps.

Prerequisites

This guide assumes you have already installed and configured Unity. If not, see the Unity Quickstart for Android for installation and setup steps.

Configure a new session with Instant Placement

Configure your app by creating a new session configuration and setting up Instant Placement mode.

  1. In Unity, create a new session configuration for the ARCore app (Assets > Create > GoogleARCore > SessionConfig).
  2. In the session configuration, choose Instant Placement Mode.

    The default value for Instant Placement Mode is Disabled. Instant Placement currently supports only Local Y Up mode.

  3. Select ARCore Device in the project hierarchy.

  4. Double-click the Session Config field and select the SessionConfig created previously.

Place an object

In a new ARCore session, perform a hit test using Frame.RaycastInstantPlacement. Then create a new Anchor using the InstantPlacementPoint pose from the hit result's Trackable.

var hitList = new List<TrackableHit>();
TrackableHit hitRaycast;
bool hitResult = Frame.RaycastInstantPlacement(
  position.x, position.y, approximateDistance, out hitRaycast);

if (hitResult) {
  // Place a pin object at the hit.
  var pinObject = Instantiate(PinPrefab, hitRaycast.Pose.position, hitRaycast.Pose.rotation);

  // Cast the trackable to an InstantPlacementPoint if you want to
  // retrieve the real time pose and tracking method. Otherwise, you
  // can use it like any other Trackable.
  InstantPlacementPoint instantPlacementPoint = hitRaycast.Trackable as InstantPlacementPoint;

  // Create an Anchor using the InstantPlacementPoint.
  Anchor anchor = instantPlacementPoint.CreateAnchor(hitRaycast.Pose);

  // Automatically sync the virtual object’s pose with the Anchor’s
  // pose in each frame.
  pinObject.transform.parent = anchor.transform;
}

Monitor Instant Placement point tracking method

If ARCore has an accurate 3D pose, the InstantPlacementPointTrackingMethod will be FullTracking. Otherwise, it will start with ScreenspaceWithApproximateDistance and transition to FullTracking once ARCore has an accurate 3D pose. The tracking method will not revert to ScreenspaceWithApproximateDistance once its tracking method is FullTracking.

Smooth the tracking method transition

The pose automatically corrects when the tracking method of the InstantPlacementPoint changes from approximated distance to full tracking. When this happens, the object jumps.

When the tracking method changes from ScreenspaceWithApproximateDistance in one frame, to FullTracking in the next frame, the pose will jump from its initial location based on the provided approximate distance to a new location at an accurate distance.

This instantaneous change in pose will change the apparent scale of any objects that are anchored to the InstantPlacementPoint. That is, an object will suddenly appear larger or smaller than it was in the previous frame.

The following code shows how to avoid the visual jump by interpolating the pose over time, from the last frame reporting ScreenspaceWithApproximateDistance to the new pose from the frame reporting FullTracking.

To avoid a sudden visible pose change, interpolate the virtual object’s current pose and the InstantPlacementPoint.Pose.

// Interpolate the pose for a specific duration. Start from the first frame that
// the tracking method changes. End after the transitionTime has
// passed transitionDuration.
if (previousTrackingMethod ==
  InstantPlacementPointTrackingMethod.ScreenspaceWithApproximateDistance &&
  instantPlacementPoint.TrackingMethod ==
  InstantPlacementPointTrackingMethod.FullTracking) {
    startTransition = true;
    previousTrackingMethod = InstantPlacementPointTrackingMethod.FullTracking;
}

if (startTransition) {
  transitionTime += Time.deltaTime;
  float ratio = Mathf.Min(transitionTime, transitionDuration) / transitionDuration;

  // Use a custom function to interpolate two poses based on the ratio. Here,
  // LerpPose(Pose, Pose, float) is a generic interpolation function containing
  // a current value, a target value, and an interpolation ratio.
  var newPose = LerpPose(
    new Pose(pinObject.transform.position, pinObject.transform.rotation),
    instantPlacementPoint.Pose, ratio);
    pinObject.transform.position = newPose.position;
    pinObject.transform.rotation = newPose.rotation;

  if (transitionTime >= transitionDuration) {
    startTransition = false;

    // Set the parent transform to be the Anchor created on the
    // InstantPlacementPoint, so that it will automatically update the pose
    // in future frames.
    Anchor anchor = instantPlacementPoint.CreateAnchor(Pose.identity);
    pinObject.transform.parent = anchor.transform;
  }
}