空間アンカー
はじめに
このサンプルでは、現実世界の特定の箇所を正確に追跡するために空間アンカーを作成および破棄する方法を紹介します。
空間アンカーに関する基本的な情報や、AR FoundationのAR Anchor Manager
コンポーネントの機能については、Unityのドキュメントを参照してください。
機能の有効化
この機能を使用するには、以下のOpenXRのプロジェクト設定でSpatial Anchorsにチェックする必要があります。
Project Settings > XR Plug-in Management > OpenXR (Androidタブ)
サンプルのインポート
まだサンプルをインポートしていない場合は、以下の手順でインポートすることができます。
サンプルシーンは以下の場所に存在します。
Assets/Samples/Snapdragon Spaces/0.XX.0/Core Samples/Scenes/Anchor Sample/Anchor Sample.unity
サンプルの仕組み
シーン内では、アンカーに関するUIパネルがカメラから2メートル先に配置されています。
Place anchor on surfaces
(平面にアンカーを配置) トグルを有効にすると、現実世界の平面に対するアンカーの位置を特定するために、毎フレーム頭部の中心から前方にレイが飛ばされます。
ヒットが検出されると、配置されるギズモは黄色に変わります。
スマートフォンのタッチパッドをタップするか、視線インタラクタを選択した場合に表示されるUIパネルで視線を操作すると、空のゲームオブジェクトとARAnchor
のゲームオブジェクトがインスタンス化されます。
空のゲームオブジェクトには透明なギズモの3Dモデルがあり、AR Sessionによってトラッキングされます。
ARアンカーのギズモは、ARAnchorManager
のanchorsChanged
イベントによって更新され、トラッキング状態を表します。
public GameObject GizmoTrackedAnchor;
public GameObject GizmoUntrackedAnchor;
private override void Start() {
FindObjectOfType<ARAnchorManager>().anchorsChanged += OnAnchorsChanged;
}
private void OnAnchorsChanged(ARAnchorsChangedEventArgs args) {
foreach (var anchor in args.added) {
...
}
foreach (var anchor in args.updated) {
Destroy(anchor.transform.GetChild(0).gameObject);
var newGizmo = Instantiate(anchor.trackingState == TrackingState.None ? GizmoUntrackedAnchor : GizmoTrackedAnchor);
newGizmo.transform.SetParent(anchor.transform, false);
}
foreach (var anchor in args.removed) {
...
}
}
全てのアンカーの破壊
全てのアンカーとギズモは、UIのDestroy All Anchors
を選択することで破壊できます。
削除コマンドは、すべて削除された後に「Select」ボタンでアンカーが作成されるのを防ぐために、遅延を伴って発行されます。
空間アンカーストア
トラッキング用のマップを精度高く生成し、保存と読み込みの時間を短縮するために、現実世界では必ず周囲を見回してください。
一度に複数のアンカーを保存するとメインスレッドがブロックされるため、コールバックを使用して後続のアンカーを保存する必要があります。
AR Anchor Managerの隣にSpaces Anchor Storeコンポーネントを追加することで、アンカーをローカルに保存し、後のセッションで認識と追跡を行うことができます。
このコンポーネントは、アンカ ーのロードと保存、保存したアンカーの削除、アンカーのローカルストレージのクリアのためのAPIを提供します。
namespace Qualcomm.Snapdragon.Spaces
{
public class SpacesAnchorStore
{
public void ClearStore();
public void SaveAnchor(ARAnchor anchor, string anchorName, Action<bool> onSavedCallback = null);
public void SaveAnchor(ARAnchor anchor, Action<bool> onSavedCallback = null);
public void SaveAnchorWithResult(ARAnchor anchor, string anchorName, Action<SaveAnchorResult> onSavedCallback = null);
public void SaveAnchorWithResult(ARAnchor anchor, Action<SaveAnchorResult> onSavedCallback = null);
public void DeleteSavedAnchor(string anchorName);
public void LoadSavedAnchor(string anchorName, Action<bool> onLoadedCallback = null);
public void LoadAllSavedAnchors(Action<bool> onLoadedCallback = null);
public string[] GetSavedAnchorNames();
public string GetSavedAnchorNameFromARAnchor(ARAnchor anchor);
}
}
これらのメソッドについて簡単に紹介します。
-
ClearStore
- アンカーのローカルストレージをクリアします。
-
SaveAnchor
AR Anchor
オブジェクトを指定された名前または生成されたハッシュで保存します。完了時にコールバックを呼び出すことができます。
-
SaveAnchorWithResult
- 指定された名前または生成されたハッシュで、
AR Anchor
オブジェクトを保存します。完了時にコールバックを呼び出すことができます。 SaveAnchorResult
に指定できる値は以下の通りです。PENDING
: アンカーは保存を保留中です。通常は見ることができないので、代わりにARAnchor.pending
を使用してください。SAVED
: ローカルストレージに正常に保存されました。FAILURE_RUNTIME_ERROR
: ランタイムエラーのため、ローカルストレージに保存されませんでした。FAILURE_STORE_NOT_LOADED
: Spaces Anchor Storeの読み込みに失敗したため、ローカルストレージに保存されませんでした。FAILURE_INSUFFICIENT_QUALITY
: 環境マップの品質が不十分なため、ローカルストレージに保存されませんでした。
- 指定された名前または生成されたハッシュで、
-
DeleteSavedAnchor
- ローカルストレージから名前を指定して保存されたアンカーを削除します。
-
LoadSavedAnchor
- ローカルストレージからアンカーをロードし、シーン内でアンカーを見つけようとします。アンカーが見つかった場合、
AR Anchor
オブジェクトがインスタンス化されます。ロードされたアンカーは、ARAnchorManager
のanchorsChanged
イベント に追加されたものとしてリストされます。保存されたアンカーの名前はGetSavedAnchorNames
で取得できます。完了時にコールバックを呼び出すことができます。
- ローカルストレージからアンカーをロードし、シーン内でアンカーを見つけようとします。アンカーが見つかった場合、
-
LoadAllSavedAnchors
- すべてのアンカーをストレージからロードし、シーン内で位置を特定しようとします。
LoadSavedAnchor
と同様に、AR Anchor
オブジェクトは認識されるとインスタンス化されます。
- すべてのアンカーをストレージからロードし、シーン内で位置を特定しようとします。
-
GetSavedAnchorNames
- 保存されているすべてのアンカーを名前で返します。
-
GetSavedAnchorNameFromARAnchor
- 追跡された
AR Anchor
オブジェクトが以前保存されたものであれば、このメソッドはその名前を返し、そうでなければ空文字列を返します。このメソッドは、アンカーが保存されているかどうかをチェックするために使用できます。
- 追跡された
サンプルでのアンカーの保存、削除、読み込み
Save new anchors to local store
(新しいアンカーをローカルに保存)のトグルを有効にすると、新しいアンカーが作成されるたびに、そのアンカーはローカルに保存されます。
つまり、シーンにAR Anchor Manager
がある限り、この保存されたアンカーは他の通常のアンカーとして再作成され、トラッキングされます。
通常のアンカーと保存されたアンカーを区別するために、アンカーの中心に立方体のメッシュが生成されます。立方体が赤い場合は、保存されたアンカーがトラッキングされていないことを意味し、白い場合はトラッキングされていることを意味します。
Load All Saved Anchors
をクリックすると、ローカルに保存されているすべてのアンカーが読み込まれ、その位置を特定しようとします。一方、Clear Store
をクリックすると、ローカル・ストアに保存されているすべてのアンカーが削除されます。この操作では、ストアからロードされた既存のアンカーは破棄されません。