Learn how to use the Instant Placement API in your own apps.
Prerequisites
Make sure that you understand fundamental AR concepts and how to configure an ARCore session before proceeding.
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.
- In Unity, create a new session configuration for the ARCore app (Assets > Create > GoogleARCore > SessionConfig).
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.
Select ARCore Device in the project hierarchy.
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;
}
Instant Placement supports
screen space tracking,
automatically switching to full tracking once the Instant Placement point is
anchored in the real world. Retrieve the current pose with
InstantPlacementPoint.Pose
.
Get the current tracking method with
InstantPlacementPoint.TrackingMethod
.
Although ARCore can perform Instant Placement hit tests against surfaces of any orientation, hit results will always return a pose with +Y up, against the direction of gravity. On horizontal surfaces, hit tests return accurate positions much faster.
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;
}
}