
ホログラムを配置したり、一緒に移動したり、場合によっては他のホログラムに対して自分自身を相対的に配置したりすることには、Mixed Reality アプリケーションを作成する際の大部分を占めます。 この記事では、World Locking Tools を使用した推奨されるソリューションについて紹介しますが、Unity プロジェクトで空間アンカーを手動で設定する方法も取り上げています。 コードに移動する前に、Unity が独自のエンジンで座標空間とアンカーを処理する方法を理解することが重要です。
世界規模の座標系
現在、ゲーム、データ視覚化アプリ、または仮想現実アプリを作成する場合、一般的なアプローチは、他のすべての座標が確実にマップできる 1 つの絶対的なワールド座標系を確立することです。 その環境では、その空間における任意の 2 つのオブジェクトの位置関係を定義する安定した変換が常に見つかります。 これらのオブジェクトを移動しなかった場合、それらの相対変換は常に同じままです。 この種のグローバル座標系は、すべてのジオメトリを事前に知っている純粋な仮想世界をレンダリングするときに簡単に取得できます。 今日のルームスケールの VR アプリでは、通常、この種の絶対的ルームスケール座標系の原点がフロアに確立されます。
これに対し、HoloLens などのテザリングされていない Mixed Reality デバイスは、世界をセンサーにより動的に認識し、ユーザーが建物のフロア全体を何メートルも歩き回るに従って、その周囲に関する知識を経時的に調整し続けます。 世界規模のエクスペリエンスでは、すべてのホログラムを単純な固定座標系に配置した場合、それらのホログラムは、世界に基づいて、または互いに相対的に、経時的に流動します。
たとえば、ヘッドセットは現在、世界の 2 つの場所が 4 メートル離れていると考え、その後、その認識を改善し、その場所が実際には 3.9 メートル離れていることを学習する可能性があります。 これらのホログラムが当初 1 つの固定座標系で 4 メートル離れた位置に配置されていた場合、そのうちの 1 つは常に現実世界から 0.1 メートル離れた場所に表示されます。
Unity に空間 アンカーを 手動で配置して、ユーザーがモバイルのときに物理世界でのホログラムの位置を維持できます。 ただし、これにより、仮想世界内の自己整合性が犠牲にされます。 別々のアンカーが常に互いに関連して移動し、グローバル座標空間を移動しています。 このシナリオでは、レイアウトのような単純なタスクが困難になります。 物理シミュレーションも問題になる可能性があります。
World Locking Tools (WLT) を使用すると、両方の世界を最適に利用できます。ユーザーが移動すると、仮想シーン全体に広がる空間アンカーの内部供給を使用して、1 つの固定座標系が安定化されます。 WLTにより、フレームごとに、カメラの座標とそれらの空間アンカーが分析されます。 WLTは、ユーザーの頭の座標の修正を補正するために世界のすべての座標を変更するのではなく、頭の座標を修正するだけです。
ワールド ロックアプローチを選択する
可能であれば、ホログラムの配置に World Locking Tools を使用します。
ワールド ロック ツール は、仮想マーカーと実際のマーカーの間の目に見える不整合を最小限に抑える安定した座標系を提供します。 ワールド ロック ツールでは、グループの個々のアンカーを使用してオブジェクトの各グループをロックするのではなく、アンカーの共有プールでシーン全体をロックします。
ワールド ロック ツールは、空間アンカーの内部作成と管理を自動的に処理します。 ホログラムのワールド ロックを維持するために ARAnchorManager や WorldAnchor と対話する必要はありません。
- OpenXR または Windows XR プラグインを使用する Unity 2019/2020 の場合は、 ARAnchorManager を使用します。
- 以前の Unity バージョンまたは WSA プロジェクトの場合は、 WorldAnchor を使用します。
ワールド ロックを設定する
ワールド ロック ツールの使用を開始するには、Mixed Reality Feature Tool ダウンロードします。 基本の詳細については、概要、クイック スタート、その他の便利なトピックへのリンクについては、メインの World Locking Tools のドキュメント ページを参照してください。
自動セットアップ
プロジェクトの準備ができたら、Mixed Reality > World Locking Tools から、シーンの構成ユーティリティを実行します。

重要
シーンの構成ユーティリティは、いつでも再実行できます。 たとえば、AR ターゲットがレガシから XR SDK に変更されている場合は、再実行する必要があります。 シーンが既に適切に構成されている場合、ユーティリティを実行しても効果はありません。
ビジュアライザー
初期の開発中に、ビジュアライザーを追加すると、WLT が適切にセットアップされて動作するようにするうえで役立ちます。 これらは、実稼働パフォーマンスのために、または何らかの理由で不要になった場合は、ビジュアライザーの削除ユーティリティを使用して削除できます。 ビジュアライザーの詳細については、ツールのドキュメントを参照してください。
Namespace: UnityEngine.XR.WSA
Type: WorldAnchor
重要な手法は、 空間アンカーを作成し ユーザーがローミングした距離に関係なく、物理的な世界でホログラムのクラスターを正確にロックし、後のセッションでこれらのホログラムをもう一度 します。
以前の Unity バージョンでは、 WorldAnchor Unity コンポーネントを GameObject に追加して、空間アンカーを作成します。
ワールド アンカーを追加する
ワールド アンカーを追加するには、現実の世界でアンカーに行う変換を使用して、ゲーム オブジェクトで AddComponent<WorldAnchor>() を呼び出します。
WorldAnchor anchor = gameObject.AddComponent<WorldAnchor>();
このゲーム オブジェクトは、物理世界の現在の位置に固定されるようになりました。 Unity ワールド座標が時間の経過と同時に少し調整され、物理的な配置が保証される場合があります。 今後 アプリ セッションでこの固定された場所を見つけるには ワールド アンカーを読み込む方法に関するページを参照してください。
ワールド アンカーを削除する
GameObjectが物理的なワールドの場所にロックされなくなり、このフレームを移動する予定がない場合は、ワールド アンカー コンポーネントでDestroyを呼び出します。
Destroy(gameObject.GetComponent<WorldAnchor>());
このフレーム GameObject を移動する場合は、代わりに DestroyImmediate を呼び出します。
DestroyImmediate(gameObject.GetComponent<WorldAnchor>());
ワールド アンカーゲームオブジェクトを移動する
ワールド アンカーがオンになっている間は、 GameObject を移動することはできません。 このフレーム GameObject を移動する必要がある場合は、次の操作を行う必要があります。
DestroyImmediate ワールド アンカー コンポーネント。
GameObjectを移動します。
GameObjectに新しいワールド アンカー コンポーネントを追加します。
DestroyImmediate(gameObject.GetComponent<WorldAnchor>());
gameObject.transform.position = new Vector3(0, 0, 2);
WorldAnchor anchor = gameObject.AddComponent<WorldAnchor>();
検索可能性の変更を処理する
ワールド アンカーは、ある時点で物理世界で見つからない可能性があります。 その後、Unity はアンカーオブジェクトの変換を更新しません。 この状況は、アプリの実行中にも発生する可能性があります。 位置の変更を処理しないと、オブジェクトが世界の正しい物理的な場所に表示されません。
検索可能性の変更が通知されるようにするには、次のようにします。
OnTrackingChanged イベントをサブスクライブします。 OnTrackingChanged イベントは、基になる空間アンカーが、検索可能な状態または検索できない状態の間で変化するたびに呼び出されます。
anchor.OnTrackingChanged += Anchor_OnTrackingChanged;
イベントを処理します。
private void Anchor_OnTrackingChanged(WorldAnchor self, bool located)
{
// This simply activates/deactivates this object and all children when tracking changes
self.gameObject.SetActiveRecursively(located);
}
アンカーが直ちに配置された場合、アンカーのisLocated プロパティは、AddComponent<WorldAnchor>()が戻ったときにtrueに設定されます。 そのため、 OnTrackingChanged イベントはトリガーされません。 よりクリーンなパターンは、アンカーをアタッチした後、初期IsLocated状態でOnTrackingChanged ハンドラーを呼び出す方法です。
Anchor_OnTrackingChanged(anchor, anchor.isLocated);
永続的なワールド ロック
空間アンカーにより、アプリケーション セッション間で現実世界の空間のホログラムが保存されます。 HoloLens アンカー ストアに保存すると、空間アンカーを見つけてさまざまなセッションに読み込むことができます。インターネット接続がない場合に最適なフォールバックです。
既定では、ワールド ロック ツールは、ローカル空間アンカーの永続化をサポートするデバイス上のセッション全体で、物理世界に対する Unity の座標系を復元します。 アプリケーションを終了して再実行した後に、物理世界の同じ場所にホログラムを表示するには、アプリケーションがホログラムに同じポーズを復元するだけで済むだけです。

アプリケーションでさらに細かい制御が必要な場合は、インスペクターで Auto-Save および Auto-Load を無効にし、スクリプトから永続化を管理できます。 詳細については、「 Persist 空間座標系」を参照してください。
World Locking Tools では、HoloLens デバイスでのみローカル アンカー永続化がサポートされます。
XRAnchorStoreと呼ばれる API を使用すると、セッション間でアンカーを永続化できます。 XRAnchorStoreは、デバイスに保存されているアンカーを表します。 Unity シーンの ARAnchors からアンカーを保持したり、ストレージから新しい ARAnchorsにアンカーを読み込んだり、ストレージからアンカーを削除することができます。
Note
これらのアンカーは、同じデバイスに保存して読み込みます。
名前空間
Unity 2020 および OpenXR の場合:
using Microsoft.MixedReality.ARSubsystems.XRAnchorStore
Unity 2019/2020 + Windows XR プラグインの場合:
using UnityEngine.XR.WindowsMR.XRAnchorStore
パブリック メソッド
{
// A list of all persisted anchors, which can be loaded.
public IReadOnlyList<string> PersistedAnchorNames { get; }
// Clear all persisted anchors
public void Clear();
// Load a single persisted anchor by name. The ARAnchorManager will create this new anchor and report it in
// the ARAnchorManager.anchorsChanged event. The TrackableId returned here is the same TrackableId the
// ARAnchor will have when it is instantiated.
public TrackableId LoadAnchor(string name);
// Attempts to persist an existing ARAnchor with the given TrackableId to the local store. Returns true if
// the storage is successful, false otherwise.
public bool TryPersistAnchor(TrackableId id, string name);
// Removes a single persisted anchor from the anchor store. This will not affect any ARAnchors in the Unity
// scene, only the anchors in storage.
public void UnpersistAnchor(string name);
}
アンカー ストア参照を取得する
Unity 2020 と OpenXR を使用して XRAnchorStore を読み込むには、ARAnchorManager のサブシステムである XRAnchorSubsystem で拡張メソッドを使用します。
public static Task<XRAnchorStore> LoadAnchorStoreAsync(this XRAnchorSubsystem anchorSubsystem)
Unity 2019/2020 および Windows XR プラグインを使用して XRAnchorStore を読み込むには、ARReferencePointManager/ARAnchorManager のサブシステムである XRReferencePointSubsystem (Unity 2019) または XRAnchorSubsystem (Unity 2020) で拡張メソッドを使用します。
// Unity 2019 + Windows XR Plugin
public static Task<XRAnchorStore> TryGetAnchorStoreAsync(this XRReferencePointSubsystem anchorSubsystem);
// Unity 2020 + Windows XR Plugin
public static Task<XRAnchorStore> TryGetAnchorStoreAsync(this XRAnchorSubsystem anchorSubsystem);
アンカー ストアを読み込む
Unity 2020 と OpenXRにアンカー ストアを読み込むには、次のように ARAnchorManager のサブシステムからアクセスします。
ARAnchorManager arAnchorManager = GetComponent<ARAnchorManager>();
XRAnchorStore anchorStore = await arAnchorManager.subsystem.LoadAnchorStoreAsync();
または、Unity 2019/2020 および Windows XR プラグインを使用します。
// Unity 2019
ARReferencePointManager arReferencePointManager = GetComponent<ARReferencePointManager>();
XRAnchorStore anchorStore = await arReferencePointManager.subsystem.TryGetAnchorStoreAsync();
// Unity 2020
ARAnchorManager arAnchorManager = GetComponent<ARAnchorManager>();
XRAnchorStore anchorStore = await arAnchorManager.subsystem.TryGetAnchorStoreAsync();
アンカーの永続化/保持解除の完全な例を確認するには、[Mixed Reality OpenXR Plugin Sample Scene]((https://github.com/microsoft/OpenXR-Unity-MixedReality-Samples) の Anchors -> Anchors Sample GameObject と AnchorsSample.cs スクリプトを確認してください。


以前の Unity バージョンまたは WSA プロジェクトでのホログラムの永続化には、 WorldAnchor を使用します。
Namespace: UnityEngine.XR.WSA.Persistence
Class: WorldAnchorStore
WorldAnchorStore は、ホログラムがアプリケーションのインスタンス間で特定の現実世界の位置に留まるホログラフィック エクスペリエンスを作成します。 ユーザーは、必要に応じて個々のホログラムをピン留めし、後でアプリ セッション上の同じ場所でホログラムを見つけることができます。
WorldAnchorStoreを使用すると、セッション間でワールド アンカーの場所を保持できます。 セッション間でホログラムを保持するには、特定のワールド アンカーを使用する GameObjects を個別に追跡します。 ワールド アンカーを使用して GameObject ルートを作成し、ローカル位置オフセットを使用して子ホログラムをアンカーできます。
以前のセッションからホログラムを読み込むには、次のようにします。
WorldAnchorStore を取得します。
- ワールド アンカー アプリ データを読み込みます。ワールド アンカーの ID が提供されます。
- ワールド アンカーを ID で読み込みます。
将来のセッションのためにホログラムを保存するには、次のようにします。
WorldAnchorStore を取得します。
- ID を指定してワールド アンカーを保存します。
- ワールド アンカーに関連するアプリ データを ID と共に保存します。
WorldAnchorStore を取得します。
操作を実行する準備ができたらわかるように、 WorldAnchorStoreへの参照を保持します。 この呼び出しは非同期であるため、アプリが起動するとすぐに次の呼び出しを行うことができます。
WorldAnchorStore.GetAsync(StoreLoaded);
StoreLoaded は、 WorldAnchorStore の読み込みが完了したときにハンドラーです。
private void StoreLoaded(WorldAnchorStore store)
{
this.store = store;
}
これで、 WorldAnchorStoreへの参照が作成されました。これを使用して、特定のワールド アンカーを保存して読み込むことができます。
ワールド アンカーを保存する
ワールド アンカーを保存するには、ワールド アンカーに名前を付けて、前に取得した WorldAnchorStore に渡します。 2 つのアンカーを同じ文字列に保存しようとすると、 store.Save は false を返します。 新しい保存を保存する前に、前の保存を削除します。
private void SaveGame()
{
// Save data about holograms that this world anchor positions
if (!this.savedRoot) // Only save the root once
{
this.savedRoot = this.store.Save("rootGameObject", anchor);
Assert(this.savedRoot);
}
}
ワールド アンカーを読み込む
ワールド アンカーを読み込むには:
private void LoadGame()
{
// Saved data about holograms that this world anchor positions:
this.savedRoot = this.store.Load("rootGameObject", rootGameObject);
if (!this.savedRoot)
{
// Game root not saved. Re-place objects or start over.
}
}
store.Delete()を使用して、以前に保存したアンカーを削除したり、store.Clear()して以前に保存したすべてのデータを削除したりすることもできます。
既存のアンカーを列挙する
格納されているアンカーを一覧表示するには、 GetAllIdsを呼び出します。
string[] ids = this.store.GetAllIds();
for (int index = 0; index < ids.Length; index++)
{
Debug.Log(ids[index]);
}
次のステップ
ワールド ロックされた座標空間を共有する:
空間マッピングについて説明します。
Unity 開発チェックポイントに戻ります。
関連項目