本日は Meta Quest の技術調査枠です。
Meta QuestのPersist Content Across Sessionsのドキュメントページが日本語訳されていなかったので参照ページを翻訳しつつ読みました。
前回記事
以下の前回記事の続きです。
bluebirdofoz.hatenablog.com
OVRSpatialAnchorコンポーネント
OVRSpatialAnchor コンポーネントは空間アンカーのライフサイクルをカプセル化したものです。
(作成、破棄、ストレージへの保存、消去など)
Unityライフサイクル | 効果 |
---|---|
Start() | 新しいアンカーを作成します(既存のアンカーから割り当てた場合を除く) |
Update() | GameObject の transform を空間アンカーのポーズから設定します |
Destroy() | 空間アンカーを消去します |
空間アンカーは Unity では System.Guid で表される一意の識別子(UUID)によって識別されます。
UUID はアプリケーションやセッションのライフタイムに関係なく保持されます。
空間アンカーの作成
Meta Quest のランタイムで新しい空間アンカーを作成するには任意の GameObject に OVRSpatialAnchor コンポーネントを追加します。
gameObject.AddComponent<OVRSpatialAnchor>();
OVRSpatialAnchor コンポーネントはインスタンス化の次のフレームで現在の transform に新しいアンカーを生成します。
空間アンカーの基礎となるランタイムは非同期なので UUID はすぐに有効にはなりません。
Meta Quest ランタイムで空間アンカーを正常に作成すると OVRSpatialAnchor コンポーネントは自動的に transform を更新します。
空間アンカーは時間の経過とともに微妙にずれることがあるため、この更新が必要になります。
空間アンカーの保存
OVRSpatialAnchor の Save メソッドを使用すると空間アンカーを永続化することができます。
public void Save(SaveOptions saveOptions, Action<OVRSpatialAnchor, bool> onComplete = null)
saveOptions パラメータは空間アンカーをローカルストレージとクラウドストレージのどちらに保存するかを決定します。
他のユーザーとアンカーを共有するにはまずクラウドストレージに保存する必要があります。
保存操作は非同期です。保存操作が完了したときに通知するデリゲートをオプションで指定することができます。
デリゲートは以下の2つの引数を取ります。
・OVRSpatialAnchor: 保存する空間アンカー
・bool: 操作が成功したか
GetComponent<OVRSpatialAnchor>().Save((anchor, success) => { ShowSaveIcon = success; });
空間アンカーの読み込み
空間アンカーの読み込みには幾つかの段階があります。
1.未割り当ての空間アンカーの読み込み
割り当てされていない空間アンカーのコレクションをロードします。
未割り当ての空間アンカーとは以前にストレージに保存したが、まだ OVRSpatialAnchor コンポーネントに割り当てていない空間アンカーのことです。
読み込み操作は非同期で動作し、完了するまでに複数のフレームがかかることがあります。
public static bool LoadUnboundAnchors(LoadOptions options, Action<UnboundAnchor[]> onComplete)
LoadOptions は読み込みする UUID の明示的なリストを必要とします。
この操作は非同期なので、結果を処理するために onComplete コールバックを利用する必要があります。
空間アンカーをローカライズする
空間アンカーをローカライズすると、システムは現実世界における空間アンカーのポーズを決定します。
空間アンカーに関連するコンテンツがある場合、関連するコンテンツをインスタンス化する前に空間アンカーをローカライズしておく必要があります。
この操作がすぐに必要でない場合は、この手順を省略することができます。
public void Localize(Action<UnboundAnchor, bool> onComplete = null, double timeout = 0)
この段階も非同期です。
空間アンカーがユーザーの背後にあることなどが原因で、空間アンカーが認識できない箇所にあったり、空間のマッピングが不十分だったりすると、本処理が失敗することがあります。
その場合は空間アンカーを再びローカライズさせるか、ユーザが周囲を見回すように誘導することも考えられます。
空間アンカーによってはすでにローカライズされている場合があります。この場合は、UnboundAnchor の Localized プロパティを使用して確認できます。
public bool Localized { get; }
各空間アンカーを OVRSpatialAnchor に割り当てる
空間アンカーは OVRSpatialAnchor コンポーネントに割り当てて、そのライフサイクルを管理し、他の機能(保存、消去、破壊など)にアクセスできるようにします。
OVRSpatialAnchor コンポーネントをインスタンス化して後、すぐに未割り当ての空間アンカーを割り当てる必要があります。
void OnLocalized(OVRSpatialAnchor.UnboundAnchor unboundAnchor, bool success) { if (!success) return; var pose = unboundAnchor.Pose; var spatialAnchor = Instantiate(_anchorPrefab, pose.position, pose.rotation); unboundAnchor.BindTo(spatialAnchor); }
メモ:既存の空間アンカーにバインドされていない OVRSpatialAnchor は最初のフレームの後に新しい空間アンカーを作成します。
空間アンカーを消去する
ストレージから空間アンカーを消去します。消去操作は非同期です。
消去操作が完了したときに通知するデリゲートをオプションで指定することができます。
デリゲートは以下の2つの引数を取ります。
・OVRSpatialAnchor: 消去する空間アンカー
・bool: 操作が成功したか
GetComponent<OVRSpatialAnchor>().Erase((anchor, success) => { ShowSaveIcon = !success; });