Unity での World Locking と空間アンカー
[アーティクル] 03/21/2023
7 人の共同作成者
フィードバック
この記事の内容
ホログラムを配置したり、一緒に移動したり、場合によっては他のホログラムに対して自分自身を相対的に配置したりすることは、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 を 使用します。
ワールド ロックを設定する
World Locking Tools の使用を開始するには、Mixed Reality機能ツールをダウンロードします 。 基本の詳細については、概要、クイック スタート、その他の便利なトピックへのリンクについては、メイン World Locking Tools のドキュメント ページを参照してください。
自動セットアップ
プロジェクトの準備ができたら、Mixed Reality > World Locking Tools から、シーンの構成ユーティリティを実行します。
重要
シーンの構成ユーティリティは、いつでも再実行できます。 たとえば、AR ターゲットがレガシから XR SDK に変更されている場合は、再実行する必要があります。 シーンが既に適切に構成されている場合、ユーティリティを実行しても効果はありません。
ビジュアライザー
初期の開発中に、ビジュアライザーを追加すると、WLT が適切にセットアップされて動作するようにするうえで役立ちます。 これらは、実稼働パフォーマンスのために、または何らかの理由で不要になった場合は、ビジュアライザーの削除ユーティリティを使用して削除できます。 ビジュアライザーの詳細については、ツールのドキュメント を参照してください。
名前空間: UnityEngine.XR.WSA
種類: WorldAnchor
重要な手法は、ユーザーがローミングした距離に関係なく、物理的な世界でホログラムのクラスターを正確にロックする 空間アンカー を作成し、 後のセッションでそれらのホログラムを再び見つけること です。
古い Unity バージョンでは、 WorldAnchor Unity コンポーネントを GameObject に追加することで、空間アンカーを作成します。
ワールド アンカーを追加する
ワールド アンカーを追加するには、現実の世界でアンカーに行う変換を使用して、ゲーム オブジェクトで AddComponent<WorldAnchor>()
を呼び出します。
WorldAnchor anchor = gameObject.AddComponent<WorldAnchor>();
このゲーム オブジェクトは、物理世界の現在の位置に固定されるようになりました。 Unity ワールド座標は、物理的な配置を確保するために時間の経過と同時に少し調整される場合があります。 今後のアプリ セッションでこのアンカー位置をもう一度見つけるには、「 ワールド アンカーを読み込む 」を参照してください。
ワールド アンカーを削除する
物理的なワールドの GameObject
場所にロックされないようにして、このフレームを移動しない場合は、World Anchor コンポーネントを呼び出 Destroy
します。
Destroy(gameObject.GetComponent<WorldAnchor>());
このフレームを移動する場合は、代わりに を GameObject
呼び出します DestroyImmediate
。
DestroyImmediate(gameObject.GetComponent<WorldAnchor>());
World Anchored GameObject を移動する
ワールドアンカーがオンになっている間は、 を移動 GameObject
できません。 このフレームを移動する必要がある場合は、次の GameObject
操作を行う必要があります。
DestroyImmediate
World Anchor コンポーネント。
を移動します GameObject
。
新しい World Anchor コンポーネントを に追加します 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
イベントはトリガーされません。 よりクリーンなパターンは、アンカーをアタッチした OnTrackingChanged
後に初期状態 IsLocated
でハンドラーを呼び出すパターンです。
Anchor_OnTrackingChanged(anchor, anchor.isLocated);
永続的なワールド ロック
空間アンカーにより、アプリケーション セッション間で現実世界の空間のホログラムが保存されます。 HoloLens アンカー ストアに保存すると、空間アンカーが見つかり、さまざまなセッションに読み込まれ、インターネット接続がない場合に最適なフォールバックになります。
重要
ローカル アンカーはデバイスに格納されますが、Azure 空間アンカーはクラウドに格納されます。 競合することなく、同じプロジェクトにローカルアンカーと Azure アンカーを含めることができます。 アンカーを格納するための Azure クラウド サービスの統合の詳細については、「 Azure Spatial Anchors 」を参照してください。
既定では、World Locking Tools は、ローカル空間アンカーの永続化をサポートするデバイス上のセッション間で、物理世界に対して Unity の座標系を復元します。 アプリケーションを終了して再実行した後に、物理世界の同じ場所にホログラムを表示するには、アプリケーションで同じポーズをホログラムに復元するだけで済みます。
アプリケーションで細かい制御が必要な場合は、インスペクターで 自動保存 と 自動読み込みを 無効にし、スクリプトから永続化を管理できます。 詳細については、「 空間座標系を永続化する 」を参照してください。
World Locking Tools では、HoloLens デバイスでのみローカル アンカー永続化がサポートされます。 Android、iOS、HoloLens デバイスの場合は、Azure Spatial Anchors と統合して、セッションとデバイス間での座標空間の永続化と共有をサポートします。 Azure Spatial Anchors で World Locking Tools を使用する詳細とサンプルについては、「 World Locking Tools (WLT) と Azure Spatial Anchors (ASA) の組み合わせ 」を参照してください。
と呼ばれる XRAnchorStore
API を使用すると、セッション間でアンカーを永続化できます。 XRAnchorStore
は、デバイス上に保存されたアンカーの表現です。 Unity シーンから ARAnchors
アンカーを保持したり、ストレージから新しい ARAnchors
にアンカーを読み込んだり、ストレージからアンカーを削除することができます。
名前空間
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 プラグイン サンプル シーン]((https://github.com/microsoft/OpenXR-Unity-MixedReality-Samples ) の Anchors -> Anchors - Anchors Sample GameObject と AnchorsSample.cs スクリプトをチェックします。
以前の Unity バージョンまたは WSA プロジェクトでのホログラムの永続化には、 WorldAnchor を 使用します。
名前空間: UnityEngine.XR.WSA.Persistence
クラス: 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]);
}
複数のデバイスのホログラムを保持する
Azure Spatial Anchors を使用して、ローカル ワールド アンカーから永続的なクラウド アンカーを作成できます。 アプリは、デバイスが同時に一緒にいなくても、複数の HoloLens、iOS、Android デバイス間でクラウド アンカーを見つけることができます。 クラウド アンカーは永続的であるため、複数のデバイスでは、時間の経過と同時に同じ物理的な場所で、そのアンカーに対して相対的にレンダリングされたコンテンツを確認できます。
次の手順
ワールド ロックされた座標空間を共有する:
空間マッピングについて説明します。
Unity 開発チェックポイントに戻るします。
関連項目