Unity の座標系
Windows Mixed Reality は、向き限定および座位のアプリからルーム スケールのアプリまで、広範なエクスペリエンスのスケールのアプリをサポートしています。 HoloLens では、さらに進んで、ユーザーが 5 メートルを超えて歩き、建物の床全体を探索できるワールド スケールのアプリを構築できます。
Unity で複合現実エクスペリエンスを構築する最初の手順は、座標系を理解し、アプリがターゲットとするエクスペリエンスのスケールを決定することです。
向き限定または座位スケールのエクスペリエンスの構築
Namespace: UnityEngine.XR
Type: XRDevice
向き限定や座位のエクスペリエンスを構築するには、Unity を固定の追跡空間の種類に設定する必要があります。 固定の追跡空間は、静止基準系を追跡するように Unity のワールド座標系を設定します。 固定追跡モードでは、アプリの起動時に、カメラの既定の場所 (前方が Z) の直前にあるエディターに配置されたコンテンツがユーザーの前に表示されます。
XRDevice.SetTrackingSpaceType(TrackingSpaceType.Stationary);
Namespace: UnityEngine.XR
Type: InputTracking
360 度ビデオ ビューアー (位置指定ヘッドの更新によって錯覚が台無しになる) などの純粋な向き限定のエクスペリエンスの場合は、XR.InputTracking.disablePositionalTracking を true に設定できます。
InputTracking.disablePositionalTracking = true;
座位のエクスペリエンスの場合、ユーザーが後で座位の基点をもう一度中央に揃えられるようにするために、XR.InputTracking.Recenter メソッドを呼び出すことができます。
InputTracking.Recenter();
立位スケールまたはルームスケールのエクスペリエンスを構築する
Namespace: UnityEngine.XR
Type: XRDevice
立位スケールまたはルーム スケールのエクスペリエンスの場合は、床を基準としてコンテンツを配置する必要があります。 最初の実行時に設定された、ユーザーが定義したフロア レベルの原点とオプションの部屋の境界を表す空間ステージを使用して、ユーザーのフロアについて推論します。
Unity がワールド座標系をフロアレベルで動作させていることを確認するために、Unity が RoomScale 追跡空間の種類を使用していることを設定し、テストすることができます。
if (XRDevice.SetTrackingSpaceType(TrackingSpaceType.RoomScale))
{
// RoomScale mode was set successfully. App can now assume that y=0 in Unity world coordinate represents the floor.
}
else
{
// RoomScale mode was not set successfully. App cannot make assumptions about where the floor plane is.
}
- SetTrackingSpaceType によって true が返された場合、Unity は、そのワールド座標系をステージ座標系を追跡するように切り替えています。
- SetTrackingSpaceType から false が返された場合、ユーザーが環境に床を設定していない可能性があるため、Unity はステージ座標系に切り替えることができませんでした。 false の値が戻されることはあまりありませんが、ステージが別の部屋に設定されていて、ユーザーが新しいステージを設定せずに現在の部屋にデバイスを移動した場合に発生する可能性があります。
RoomScale 追跡スペースの種類が正常に設定されると、y=0 平面に配置されたコンテンツがフロアに表示されます。 0, 0, 0 の原点は、部屋の設定時にユーザーが立っていた床の特定の場所になります (-Z は設定時に向いていた前方方向を表します)。
Namespace: UnityEngine.Experimental.XR
Type: Boundary
スクリプト コードでは、UnityEngine.Experimental.XR.Boundary 型の TryGetGeometry メソッドを呼び出して境界線の多角形を取得すると、境界線の種類として TrackedArea を指定できます。 ユーザーが境界線を定義している場合 (頂点の一覧を取得した場合)、ユーザーにルーム スケール エクスペリエンスを提供し、あなたが作成したシーンをたどることができます。
Note
ユーザーが境界線に近づくと、自動的にそれがレンダリングされます。 この多角形を使用して境界線自体をレンダリングする必要はありません。 ただし、この境界線の多角形を使用してシーン オブジェクトをレイアウトすることで、ユーザーがテレポートを使用しなくても物理的にオブジェクトに到達できるようにすることができます。
var vertices = new List<Vector3>();
if (UnityEngine.Experimental.XR.Boundary.TryGetGeometry(vertices, Boundary.Type.TrackedArea))
{
// Lay out your app's content within the boundary polygon, to ensure that users can reach it without teleporting.
}
ワールド スケールのエクスペリエンスの構築
Namespace: UnityEngine.XR.WSA
Type: WorldAnchor
ユーザーが 5 メートルを超える位置にいる HoloLens での真のワールド スケール エクスペリエンスについては、ルーム スケール エクスペリエンスに使用されるもの以外の新しい手法が必要になります。 使用する主な手法の 1 つは、空間アンカーを作成して、ユーザーがどの程度ローミングしたかに関係なく、現実世界にあるホログラムのクラスターを正確にロックし、後のセッションで再びそれらのホログラムを見つけることです。
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 を移動することはできません。 このフレームで GameObject を移動する必要がある場合は、次のことを行う必要があります。
- ワールド アンカー コンポーネントに DestroyImmediate を行う
- GameObject を移動する
- 新しいワールド アンカー コンポーネントを GameObject に追加する。
DestroyImmediate(gameObject.GetComponent<WorldAnchor>());
gameObject.transform.position = new Vector3(0, 0, 2);
WorldAnchor anchor = gameObject.AddComponent<WorldAnchor>();
検索可能性の変更の処理
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);
デバイス間でのアンカーの共有
Azure Spatial Anchors を使用して、ローカル WorldAnchor から持続性のあるクラウド アンカーを作成します。アプリはこれを複数の HoloLens、iOS、および Android デバイスで見つけることができます。 複数のデバイスで共通の空間アンカーを共有することにより、各ユーザーは、同じ物理的場所でそのアンカーを基準としてレンダリングされたコンテンツを見ることができます。 これにより、リアルタイム共有エクスペリエンスを実現できます。
Unity で共有エクスペリエンスの構築を開始するには、5 分間の Azure Spatial Anchors Unity クイック スタートをお試しください。
Azure Spatial Anchors が稼働状態になったら、Unity でアンカーを作成して見つけることができるようになります。
次の開発チェックポイント
私たちが用意した Unity 開発チェックポイント体験に従っている場合、読者は Mixed Reality コア構成要素を探索している段階にいます。 ここから、次の構成要素を続けることができます。
または、Mixed Reality プラットフォームの機能と API に移動します。
いつでも Unity 開発チェックポイントに戻ることができます。