ARCore の Cloud Anchors と永続的な Cloud Anchors

1. 概要

ARCore は、モバイル デバイスで拡張現実(AR)アプリを構築するためのプラットフォームです。Cloud Anchors API を使用すると、共通の参照フレームを共有する AR アプリを作成して、複数のユーザーが仮想コンテンツを同じ現実世界の場所に配置できます。

この Codelab では、Cloud Anchors API について説明します。既存の ARCore アプリを取得して、Cloud Anchors を使用するように変更し、共有の AR エクスペリエンスを作成します。

ARCore Anchors と永続的な Cloud Anchors

ARCore の基本コンセプトは、Anchor です。これは、現実世界での定位置を表すものです。ARCore では、モーション トラッキングが時間の経過とともに改善され、Anchor のポーズの値が自動的に調整されます。

Cloud Anchors とは、クラウド内でホストされる Anchors です。複数のユーザーによって解決され、複数のユーザーとそのデバイスにわたる共通の参照フレームを確立できます。

アンカーをホストする

アンカーをホストすると、次の処理が行われます。

  1. 現実世界に対する Anchor のポーズがクラウドにアップロードされ、Cloud Anchor ID が取得されます。
    Cloud Anchor ID とは、このアンカーの解決を希望するユーザーに送る必要がある文字列です。
  2. アンカーのビジュアル データを含むデータセットは、Google サーバーにアップロードされます。
    このデータセットには、直前にデバイスで認識されたビジュアル データが含まれます。ホストする前にデバイスを少し動かして、アンカーの周囲をさまざまな視点から撮影すると、位置の推定がより正確になります。

Cloud Anchor ID の転送

この Codelab では、Firebase を使用して Cloud Anchor ID を転送します。Cloud Anchor ID は、他の手段で自由に共有できます。

アンカーを解決する

Cloud Anchor API を使用すると、Cloud Anchor ID でアンカーを解決できます。これによって、ホストされた元のアンカーと同じ物理的な場所に、新しいアンカーが作成されます。解決処理の間、デバイスはホストされた元のアンカーと同じ物理環境に向けられている必要があります。

永続的な Cloud Anchors

1.20 より前のバージョンでは、Cloud Anchor を解決できるのはホストされた後 24 時間のみに限定されていました。Persistent Cloud Anchors API では、作成後 1 日~365 日の間解決できるクラウド アンカーを作成できます。

作成するアプリの概要

この Codelab では、既存の ARCore アプリをベースにしてアプリを構築します。この Codelab を終了すると、アプリは次のようになります。

  • 永続的な Cloud Anchors をホストして、Cloud Anchor ID を取得できます。
  • Android SharedPreferences を使用して簡単に取得できるように、Cloud Anchor ID をデバイスに保存します。
  • 保存した Cloud Anchor ID を使用して、以前にホストされたアンカーを解決します。これにより、この Codelab の目的に対し、1 つのデバイスで複数のユーザー エクスペリエンスのシミュレーションを簡単に行えます。
  • Cloud Anchor ID を、同じアプリを実行している別のデバイスと共有して、複数のユーザーが同じ位置に Android の像を表示できるようにします。

Android の像は、Cloud Anchor の位置にレンダリングされます。

学習内容

  • ARCore SDK を使用して Anchors をホストし、Cloud Anchor ID を取得する方法。
  • Cloud Anchor ID を使用して Anchors を解決する方法。
  • Cloud Anchor ID を保存して同じデバイスまたは別のデバイスの異なる AR セッション間で共有する方法。

必要なもの

2. 開発環境を設定する

開発マシンのセットアップ

ARCore デバイスを USB ケーブルでパソコンに接続します。開発用デバイスでは USB デバッグを許可してください。

ターミナルを開いて、次のように adb devices を実行します。

adb devices

List of devices attached
<DEVICE_SERIAL_NUMBER>    device

<DEVICE_SERIAL_NUMBER> は、デバイス固有の文字列です。デバイスが 1 台だけ表示されていることを確認してから、次へ進んでください。

コードのダウンロードとインストール

次のようにしてリポジトリのクローンを作成できます。

git clone https://github.com/googlecodelabs/arcore-cloud-anchors.git

または、次のボタンで ZIP ファイルをダウンロードして展開します。

Android Studio を起動します。[Open an existing Android Studio project] をクリックします。次に、先ほどダウンロードした ZIP ファイルを展開したディレクトリに移動し、arcore-cloud-anchors ディレクトリをダブルクリックします。

これは複数のモジュールがある単一の Gradle プロジェクトです。Android Studio の左上に [Project] ペインがまだ表示されていない場合は、プルダウン メニューから [Projects] をクリックします。結果は次のようになります。

52282f0415fdbdcb.png

主に work モジュールで作業します。他のモジュールには、使用できる有用なラッパークラスのセットを含む helpers モジュールが含まれています。また、Codelab の各パートに完全な解答が用意されています。helpers モジュールを除き、各モジュールはビルド可能なアプリです。

Android Gradle プラグインのアップグレードを提案するダイアログが表示されたら、[Don't remember me again for this project] をクリックします。

31a93c7e9cc58b53.png

[Run] > [Run...] > [‘work'] の順にクリックします。表示された [Select Deployment Target] ダイアログの [Connected Devices] の下に開発用デバイスが表示されます。開発用デバイスを選択して、[OK] をクリックします。Android Studio によって初期アプリがビルドされ、開発用デバイスで実行されます。

初めてアプリを実行する場合は、CAMERA 権限がリクエストされます。[ALLOW] をタップして続行します。

f7ea81f71a4b969e.png

アプリの使用方法

  1. デバイスを動かして平面が検出されるようにします。平面が検出されると、ドット面として表示されます。
  2. 平面上のどこかをタップしてアンカーを置きます。アンカーを置いた場所に Android のキャラクターが描画されます。このアプリで一度に置けるアンカーは 1 個だけです。
  3. デバイスを動かします。デバイスを動かしても、キャラクターは同じ場所に留まります。
  4. [CLEAR] ボタンを押してアンカーを削除します。これにより、別のアンカーを配置できます。

現在、このアプリは、ARCore が提供するモーション トラッキングのみを使用しており、アプリの 1 回の実行の中でアンカーを追跡します。アプリを終了、中断、再起動すると、以前に配置したアンカーとそれに関連する情報(ポーズなど)は失われます。

次のセクションでは、このアプリをベースとして、AR セッションをまたいでアンカーを共有する方法を学習します。

3. アンカーをホストする

このセクションでは、work プロジェクトを変更してアンカーをホストします。コードを記述する前に、アプリの構成にいくつかの変更を加える必要があります。

INTERNET 権限を宣言する

Cloud Anchors は ARCore Cloud Anchor API サービスとの通信を必要とするため、アプリにはインターネットにアクセスするための権限が必要です。

AndroidManifest.xml ファイルで、android.permission.CAMERA 権限の宣言のすぐ下に、次の行を追加します。

<!-- Find this line... -->
<uses-permission android:name="android.permission.CAMERA"/>

<!-- Add the line right below -->
<uses-permission android:name="android.permission.INTERNET"/>

ARCore Cloud Anchor API の有効化

  1. [ARCore Cloud Anchor API] サービスのページに移動します。
  2. プロジェクト リストで、プロジェクトを選択するか、新しいプロジェクトを作成します。
  3. [有効にする] をクリックします。

OAuth を設定する

永続的な Cloud Anchors を使用するには、OAuth を使用して ARCore Cloud Anchor サービスで認証する必要があります。

  1. Google Cloud Platform Console に移動します。
  2. プロジェクト リストからプロジェクトを選択します。
  3. [API とサービス] ページをまだ開いていない場合は、コンソールの左側のメニューを開いて、[API とサービス] を選択します。
  4. 左側のエリアで [認証情報] をクリックします。
  5. [認証情報を作成] をクリックし、[OAuth クライアント ID] を選択します。
  6. 次の値を入力します。
    • アプリケーションの種類: Android
    • パッケージ名: com.google.ar.core.codelab.cloudanchor
  7. デバッグ用の署名証明書のフィンガープリントを取得します。
    1. Android Studio プロジェクトで、[Gradle toolpane] を開きます。
    2. [cloud-anchors] > [work] > [Tasks] > [android] で、[signingReport] タスクを実行します。
    3. SHA-1 フィンガープリントを Google Cloud の [SHA-1 証明書のフィンガープリント] フィールドにコピーします。

ARCore を構成する

次に、アプリを変更して、ユーザーがタップしたときに通常のアンカーではなくホスト型アンカーを作成するようにします。そのためには、Cloud Anchors を有効にする ARCore Session を構成する必要があります。

CloudAnchorFragment.java ファイルに、次のコードを追加します。

// Find this line...
session = new Session(requireActivity());

// Add these lines right below:
// Configure the session.
Config config = new Config(session);
config.setCloudAnchorMode(CloudAnchorMode.ENABLED);
session.configure(config);

先に進む前に、アプリをビルドして実行してください。必ず work モジュールのみをビルドしてください。アプリが正常にビルドされ、以前と同じように動作する必要があります。

ホスト型アンカーを作成する

ARCore Cloud Anchor サービスにアップロードするホスト型アンカーを作成します。

次の新しい項目を、CloudAnchorFragment クラスに追加します。

// Find this line...
private final SnackbarHelper messageSnackbarHelper = new SnackbarHelper();

// Add this line right below.
private final CloudAnchorManager cloudAnchorManager = new CloudAnchorManager();

CloudAnchorManager クラスと SnackbarHelper クラスは、すでに用意されています。ボイラープレート コードをカプセル化する際に便利なラッパークラスがいくつか入っています。これにより、記述するコードがはるかに整理され短くなります。

onDrawFrame() メソッドに、次の行を追加します。

// Find this line...
Frame frame = session.update();

// Add this line right below:
cloudAnchorManager.onUpdate();

onClearButtonPressed メソッドを次のように変更します。

private synchronized void onClearButtonPressed() {
  // Clear the anchor from the scene.

  // The next line is the new addition.
  cloudAnchorManager.clearListeners();

  currentAnchor = null;
}

次に、以下のメソッドを CloudAnchorFragment クラスに追加します。

private synchronized void onHostedAnchorAvailable(Anchor anchor) {
  CloudAnchorState cloudState = anchor.getCloudAnchorState();
  if (cloudState == CloudAnchorState.SUCCESS) {
    messageSnackbarHelper.showMessage(
        getActivity(), "Cloud Anchor Hosted. ID: " + anchor.getCloudAnchorId());
    currentAnchor = anchor;
  } else {
    messageSnackbarHelper.showMessage(getActivity(), "Error while hosting: " + cloudState.toString());
  }
}

CloudAnchorFragment クラスの handleTap メソッドを見つけ、次の行を追加します。

//Find this line...
currentAnchor = hit.createAnchor();

// Add these lines right below:
messageSnackbarHelper.showMessage(getActivity(), "Now hosting anchor...");
cloudAnchorManager.hostCloudAnchor(session, currentAnchor, /* ttl= */ 300, this::onHostedAnchorAvailable);

Android Studio から、再度アプリを実行します。アンカーを置くと、「Now hosting anchor...」というメッセージが表示されます。ホスト処理が正常に完了すると、別のメッセージが表示されます。「Error hosting anchor: ERROR_NOT_AUTHORIZED」というエラーが表示された場合は、OAuth クライアントが正しく構成されていることを確認してください。

アンカー ID を知っており、アンカーと同じ物理空間にいる場合は、そのアンカー ID を使って、周囲の環境に対して完全に同じポーズ(位置と向き)でアンカーを作成できます。

ただし、アンカー ID は長いため、他のユーザーが手動で入力するのは困難です。以降のセクションでは、Cloud Anchor ID を簡単に取得できるようにして、同じデバイスまたは別のデバイスでアンカーの解決を行えるようにします。

4.ストア ID とアンカーを解決する

ここでは、長い Cloud Anchor ID に短いコードを割り当てて、他のユーザーが手動で入力できるようにします。Cloud Anchor ID を値として Key-Value テーブルに保存するために、Shared Preferences API を使用します。このテーブルは、アプリを強制終了し再起動しても保持されます。

StorageManager というヘルパークラスがすでに用意されています。これは、SharedPreferences API を包むラッパーで、新しい一意の短いコードを生成するメソッドと、Cloud Anchor ID を読み書きするメソッドを含んでいます。

StorageManager を使用する

CloudAnchorFragment を変更し、StorageManager を使用して短いコードで Cloud Anchor ID を保存します。これによって ID が、簡単に取得できるようになります。

CloudAnchorFragment に、次の新しい項目を作成します。

// Find this line...
private TapHelper tapHelper;

// And add the storageManager.
private final StorageManager storageManager = new StorageManager();

次に、onHostedAnchorAvailable メソッドを変更します。

private synchronized void onHostedAnchorAvailable(Anchor anchor) {
  CloudAnchorState cloudState = anchor.getCloudAnchorState();
  if (cloudState == CloudAnchorState.SUCCESS) {
    int shortCode = storageManager.nextShortCode(getActivity());
    storageManager.storeUsingShortCode(getActivity(), shortCode, anchor.getCloudAnchorId());
    messageSnackbarHelper.showMessage(
        getActivity(), "Cloud Anchor Hosted. Short code: " + shortCode);
    currentAnchor = anchor;
  } else {
    messageSnackbarHelper.showMessage(getActivity(), "Error while hosting: " + cloudState.toString());
  }
}

ここで、Android Studio から、アプリをビルドして実行します。アンカーを作成してホストすると、長い Cloud Anchor ID ではなく、短いコードが表示されます。

アンカーの設置直後

少し待った後

なお、現在 StorageManager が生成する短いコードには、常に増加した数値が割り当てられます。

次に、短いコードを入力してアンカーを再作成できるようにする UI 要素をいくつか追加します。

[RESOLVE] ボタンを追加する

[CLEAR] ボタンの横に別のボタンを追加します。これが [RESOLVE] ボタンになります。[RESOLVE] ボタンをクリックするとダイアログ ボックスが開き、ユーザーに短いコードの入力を求めます。短いコードは、StorageManager から Cloud Anchor ID を取得して、アンカーを解決するために使用されます。

ボタンを追加するには、res/layout/cloud_anchor_fragment.xml ファイルを変更する必要があります。Android Studio で、ファイルをダブルクリックし、下部にある [Text] タブをクリックすると未加工の XML が表示されます。次のように変更します。

<!-- Find this element. -->
<Button
    android:text="CLEAR"
    android:id="@+id/clear_button"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"/>

<!-- Add this element right below. -->
<Button
    android:text="RESOLVE"
    android:id="@+id/resolve_button"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"/>

ここで、CloudAnchorFragment に新しい項目を追加します。

private Button resolveButton;

新しいメソッドを追加します。

private synchronized void onResolveButtonPressed() {
  ResolveDialogFragment dialog = new ResolveDialogFragment();
  dialog.show(getFragmentMagetActivity().getSupportFragmentManagernager(), "Resolve");
}

onCreateView メソッド内で、resolveButton を次のように初期化します。

// Find these lines...
Button clearButton = rootView.findViewById(R.id.clear_button);
clearButton.setOnClickListener(v -> onClearButtonPressed());

// Add these lines right below.
resolveButton = rootView.findViewById(R.id.resolve_button);
resolveButton.setOnClickListener(v -> onResolveButtonPressed());

handleTap メソッドを見つけて変更します。

private void handleTap(Frame frame, Camera camera) {
  // ...

  // Find this line.
  currentAnchor = hit.createAnchor();

  // Add this line right below.
  getActivity().runOnUiThread(() -> resolveButton.setEnabled(false));
}

onClearButtonPressed メソッドに 1 行追加します。

private synchronized void onClearButtonPressed() {
  // Clear the anchor from the scene.
  cloudAnchorManager.clearListeners();

  // The next line is the new addition.
  resolveButton.setEnabled(true);

  currentAnchor = null;
}

Android Studio から、アプリをビルドして実行します。[CLEAR] ボタンの横に [RESOLVE] ボタンが表示されます。[RESOLVE] ボタンをクリックすると、次のようにダイアログがポップアップします。

[RESOLVE] ボタンが表示されるようになりました。

ボタンをクリックすると、このダイアログが表示されます

平面をタップしてアンカーをホストすると、[RESOLVE] ボタンが無効になりますが、[CLEAR] ボタンをタップすると再び有効になります。これは設計による動作で、一度に 1 つのアンカーのみ存在します。

[Resolve Anchor] ダイアログは何も実行しませんが、今からそれを変更します。

アンカーを解決する

CloudAnchorFragment クラスに、以下のメソッドを追加します。

private synchronized void onShortCodeEntered(int shortCode) {
  String cloudAnchorId = storageManager.getCloudAnchorId(getActivity(), shortCode);
  if (cloudAnchorId == null || cloudAnchorId.isEmpty()) {
    messageSnackbarHelper.showMessage(
        getActivity(),
        "A Cloud Anchor ID for the short code " + shortCode + " was not found.");
    return;
  }
  resolveButton.setEnabled(false);
  cloudAnchorManager.resolveCloudAnchor(
      session,
      cloudAnchorId,
      anchor -> onResolvedAnchorAvailable(anchor, shortCode));
}

private synchronized void onResolvedAnchorAvailable(Anchor anchor, int shortCode) {
  CloudAnchorState cloudState = anchor.getCloudAnchorState();
  if (cloudState == CloudAnchorState.SUCCESS) {
    messageSnackbarHelper.showMessage(getActivity(), "Cloud Anchor Resolved. Short code: " + shortCode);
    currentAnchor = anchor;
  } else {
    messageSnackbarHelper.showMessage(
        getActivity(),
        "Error while resolving anchor with short code " + shortCode + ". Error: "
            + cloudState.toString());
    resolveButton.setEnabled(true);
  }
}

次に、onResolveButtonPressed メソッドを変更します。

private synchronized void onResolveButtonPressed() {
  ResolveDialogFragment dialog = ResolveDialogFragment.createWithOkListener(
      this::onShortCodeEntered);
  dialog.show(getActivity().getSupportFragmentManager(), "Resolve");
}

Android Studio からアプリをビルドして実行し、次の手順を行います。

  1. 平面上にアンカーを作成し、それがホストされるまで待ちます。
    短いコードを覚えておいてください。
  2. [CLEAR] ボタンを押してアンカーを削除します。
  3. [RESOLVE] ボタンを押します。ステップ 1 の短いコードを入力します。
  4. アンカーは、環境に対して、配置したときと同じ位置に表示されます。
  5. アプリを強制終了してから、もう一度開きます。
  6. ステップ 3 とステップ 4 を繰り返します。新しいアンカーが、同じ位置に再び表示されるはずです。

短いコードを入力中

アンカーが正常に解決されます

5. デバイス間で共有する

アンカーの Cloud Anchor ID をデバイスのローカル ストレージに保存し、後でそれを取得して同じアンカーを再作成する方法について説明しました。しかし、Cloud Anchors の可能性を最大限に引き出すことができるのは、Cloud Anchor ID を複数のデバイス間で共有するときです。

アプリが Cloud Anchor ID を共有する方法は、自由に決めることができます。あるデバイスから他のデバイスへの文字列の転送には、どのような方法でも使用できます。この Codelab では、Firebase Realtime Database を使用してアプリのインスタンス間で Cloud Anchor ID を転送します。

Firebase の設定

このアプリで使用するために、Google アカウントで Firebase Realtime Database を設定する必要があります。これは Android Studio の Firebase Assistant で簡単に行えます。

Android Studio で、[Tools] > [Firebase] をクリックします。表示される [Assistant] ペインで、[Realtime Database] をクリックし、続いて [Save and retrieve data] をクリックします。

68e927cbf324a3b2.png

[Connect to Firebase] ボタンをクリックして、Android Studio プロジェクトを新規または既存の Firebase プロジェクトに接続します。

63f3b1ffd6bd263e.png

モジュールの選択を求めるプロンプトが表示されます。[work] モジュールを選択します。

be737c689ad6dd78.png

[Starting Connect Dialog] が表示されます。この処理には数分かかることがあります。

b48626f8672551ee.png

Google アカウントにログインし、Android Studio に戻るまで、アプリ用の Firebase プロジェクトを作成するためのウェブ ワークフローを進めます。

次に、[Assistant] ペインで、[Add the Realtime Database to your app] をクリックします。

68e0843fa2531c4c.png

表示されたダイアログで、[Target module] プルダウンから [work] を選択し、[Accept Changes] をクリックします。

155fd89533c02671.png

これにより、次のことが行われます。

  1. google-services.json ファイルを work ディレクトリに追加します。
  2. 同じディレクトリの build.gradle ファイルに数行追加します。
  3. アプリをビルドして実行します(Firebase データベースのバージョン番号に関する解決エラーが表示される場合があります)。

work モジュールの build.gradle ファイルで、次の行を探して削除します(xxxx には最新のバージョン番号が入ります)。

dependencies {
  ...
  implementation 'com.google.firebase:firebase-database:xxxx'

次に、Firebase Realtime Database をグローバルに書き込み可能に構成するため、configure your rules for public access からリンクされたページの手順を確認します(まだ操作は行わないでください)。これは、この Codelab でのテストを簡単にします。

666ebefd39019c05.png

Firebase コンソールで、Android Studio プロジェクトを接続したプロジェクトを選択してから、[BUILD] > [Realtime Database] を選択します。

Firebase Realtime Database の場所

[Create Database] をクリックし、Realtime Database を構成して設定します。

データベースの作成

適当なデータベースの場所を選択します。

次のステップで、[テストモード] のセキュリティ ルールを選択して [有効にする] をクリックします。

データベース セキュリティ

これで、アプリが Firebase データベースを使用するように構成されました。

FirebaseManager の使用

ここでは、StorageManagerFirebaseManager に置き換えます。

Android Studio で、work ディレクトリの下にある CloudAnchorFragment クラスを見つけます。StorageManagerFirebaseManager に置き換えます。

// Find this line.
private final StorageManager storageManager = new StorageManager();

// And replace it with this line.
private FirebaseManager firebaseManager;

onAttach メソッドで、firebaseManager を初期化します。

public void onAttach(@NonNull Context context) {
  super.onAttach(context);
  tapHelper = new TapHelper(context);
  trackingStateHelper = new TrackingStateHelper(requireActivity());

  // The next line is the new addition.
  firebaseManager = new FirebaseManager(context);
}

onShortCodeEntered メソッドを次のように変更します。

private synchronized void onShortCodeEntered(int shortCode) {
  firebaseManager.getCloudAnchorId(shortCode, cloudAnchorId -> {
    if (cloudAnchorId == null || cloudAnchorId.isEmpty()) {
      messageSnackbarHelper.showMessage(
          getActivity(),
          "A Cloud Anchor ID for the short code " + shortCode + " was not found.");
      return;
    }
    resolveButton.setEnabled(false);
    cloudAnchorManager.resolveCloudAnchor(
        session,
        cloudAnchorId,
        anchor -> onResolvedAnchorAvailable(anchor, shortCode));
  });
}

次に、onHostedAnchorAvailable メソッドを次のように変更します。

private synchronized void onHostedAnchorAvailable(Anchor anchor) {
  CloudAnchorState cloudState = anchor.getCloudAnchorState();
  if (cloudState == CloudAnchorState.SUCCESS) {
    String cloudAnchorId = anchor.getCloudAnchorId();
    firebaseManager.nextShortCode(shortCode -> {
      if (shortCode != null) {
        firebaseManager.storeUsingShortCode(shortCode, cloudAnchorId);
        messageSnackbarHelper.showMessage(getActivity(), "Cloud Anchor Hosted. Short code: " + shortCode);
      } else {
        // Firebase could not provide a short code.
        messageSnackbarHelper.showMessage(getActivity(), "Cloud Anchor Hosted, but could not "
                + "get a short code from Firebase.");
      }
    });
    currentAnchor = anchor;
  } else {
    messageSnackbarHelper.showMessage(getActivity(), "Error while hosting: " + cloudState.toString());
  }
}

アプリをビルドして実行します。前のセクションと同じ UI フローが表示されますが、今回は、Cloud Anchor ID とショートコードの保存に、デバイスのローカル ストレージではなく、オンライン Firebase データベースが使用される点が異なります。

マルチユーザーのテスト

マルチユーザー エクスペリエンスをテストするには、2 台のスマートフォンを使用します。

  1. 2 台のデバイスにアプリをインストールします。
  2. 一方のデバイスでアンカーをホストして、短いコードを生成します。
  3. もう一方のデバイスを使用して、その短いコードを使ってアンカーを解決します。

一方のデバイスからアンカーをホストして短いコードを取得し、もう一方のデバイスで取得した短いコードを使って同じ場所にアンカーを表示できます。

6. まとめ

これで、Codelab は終りです。

学習した内容

  • ARCore SDK を使用して Anchors をホストし、Cloud Anchor ID を取得する方法。
  • Cloud Anchor ID を使用して Anchors を解決する方法。
  • Cloud Anchor ID を保存して同じデバイスまたは別のデバイスの異なる AR セッション間で共有する方法。

詳細