独自のアプリで Instant Placement API を使用する方法を確認する。
Prerequisites
先に進む前に、AR の基本コンセプトと ARCore セッションの構成方法を理解しておいてください。
このガイドでは、すでに Unity をインストールして構成していることを前提としています。インストールされていない場合は、Unity の Android 用クイックスタートを参照してインストールと設定を行います。
インスタント セッションで新しいセッションを設定する
新しいセッション構成を作成して Instant Placement モードを設定して、アプリを構成します。
- Unity で、ARCore アプリの新しいセッション構成を作成します([Assets] > [Create] > [GoogleARCore] > [SessionConfig])。
セッション構成で、[Instant Placement Mode] を選択します。
インスタント プレースメント モードのデフォルト値は Disabled です。インスタント プレースメントでは現在、ローカル Y Up モードのみがサポートされています。
プロジェクト階層で [ARCore Device] を選択します。
[Session Config] フィールドをダブルクリックし、前に作成した
SessionConfig
を選択します。
オブジェクトを配置する
新しい ARCore セッションで、Frame.RaycastInstantPlacement を使用してヒットテストを実行します。次に、ヒット結果の Trackable
にある InstantPlacementPoint ポーズを使用して、新しい Anchor を作成します。
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 版では、画面スペースのトラッキングがサポートされており、リアルタイム プレースメント ポイントが固定されていると、自動的にフル トラッキングに切り替わります。InstantPlacementPoint.Pose
で現在のポーズを取得します。
InstantPlacementPoint.TrackingMethod
を使用して、現在のトラッキング メソッドを取得します。
ARCore では、どの向きのサーフェスに対してもインスタント プレースメントのヒットテストを実行できますが、ヒットの結果は常に重力の方向とは逆の +Y のポーズになります。水平面では、ヒットテストにより正確な位置がはるかに高速に返されます。
インスタント プレースメント ポイント トラッキング メソッドをモニタリングする
ARCore が正確な 3D ポーズを持っている場合、InstantPlacementPointTrackingMethod
は FullTracking
になります。それ以外の場合は、ScreenspaceWithApproximateDistance
から始まり、ARCore が正確な 3D ポーズを持つと FullTracking
に移行します。トラッキング メソッドは FullTracking
になると、ScreenspaceWithApproximateDistance
に戻されません。
トラッキング メソッドの移行をスムーズにする
InstantPlacementPoint
のトラッキング メソッドがおおよその距離から完全なトラッキングに変更されると、ポーズは自動的に修正されます。その場合、そのオブジェクトはジャンプします。
あるフレームのトラッキング メソッドが ScreenspaceWithApproximateDistance
から次のフレームの FullTracking
に変更されると、ポーズは指定された正確な距離に基づいて、最初の位置から正確な距離にある新しい位置までジャンプします。
このポーズの瞬間的な変化により、InstantPlacementPoint
に固定されているオブジェクトの見かけのスケールが変更されます。つまり、オブジェクトが前のフレームよりも急に大きくなったり小さくなったりします。
次のコードは、最後のフレーム レポート ScreenspaceWithApproximateDistance
からフレーム レポート FullTracking
の新しいポーズまで、時間の経過とともにポーズを補間することで、視覚的なジャンプを避ける方法を示しています。
瞬間的な姿勢の変化を避けるには、仮想オブジェクトの現在のポーズと 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;
}
}