ソルバーは、定義済みのアルゴリズムに従ってオブジェクトの位置と向きの計算を容易にするコンポーネントです。 例: ユーザーの視線入力レイキャストが交差するオブジェクトをサーフェス上に配置します。
ソルバー システムは、コンポーネントの更新順序をUnityするための信頼性の高い方法がないため、これらの変換計算の操作の順序を決定論的に定義します。
ソルバーは、オブジェクトを他のオブジェクトまたはシステムにアタッチするためのさまざまな動作を提供します。 もう 1 つの例は、カメラに基づいてユーザーの前にホバーするタグに沿ったオブジェクトです。 ソルバーをコントローラーとオブジェクトにアタッチして、コントローラーに沿ってオブジェクト タグを作成することもできます。 すべてのソルバーを安全に積み重ねることができます。たとえば、タグに沿った動作と表面磁気とモメンタムです。
使用方法
ソルバー システムは、スクリプトの 3 つのカテゴリで構成されます。
-
Solver: すべてのソルバーの派生元となる抽象基底クラス。 状態追跡、スムージング パラメーターと実装、自動ソルバー システム統合、更新順序が提供されます。 -
SolverHandler: 参照オブジェクトの追跡を に対して設定します (例: メイン カメラの変換、ハンド レイなど)。ソルバー コンポーネントの収集を処理し、適切な順序で更新を実行します。
3 番目のカテゴリはソルバー自体です。 次のソルバーは、基本的な動作の構成要素を提供します。
-
Orbital: 指定した位置にロックし、参照先オブジェクトからのオフセットを指定します。 -
ConstantViewSize: 参照先オブジェクトのビューに対して一定のサイズを維持するようにスケーリングします。 -
RadialView: 参照先オブジェクトによってキャストされたビュー 円錐内にオブジェクトを保持します。 -
Follow: 参照先オブジェクトのユーザー定義境界のセット内にオブジェクトを保持します。 -
InBetween: 追跡対象の 2 つのオブジェクトの間にオブジェクトを保持します。 -
SurfaceMagnetism: レイをワールド内のサーフェスにキャストし、オブジェクトをそのサーフェスに位置合わせします。 -
DirectionalIndicator: オブジェクトの位置と向きを方向インジケーターとして決定します。 SolverHandler Tracked Target の参照ポイントから、このインジケーターは指定された DirectTarget に向きます。 -
Momentum: 加速度/速度/摩擦を適用して、他のソルバー/コンポーネントによって移動されるオブジェクトの運動量とバネ性をシミュレートします。 -
HandConstraint: 手と GameObject が交差しない領域の手に従う制約オブジェクト。 メニューなどの手で制限された対話型コンテンツに役立ちます。このソルバーは、XRNodeを操作することを目的としています。 -
HandConstraintPalmUp: HandConstraint から派生しますが、アクティブ化前に手のひらがユーザーに向いているかどうかをテストするロジックが含まれています。 このソルバーは、XRNodeコントローラーでのみ機能し、他のコントローラーの種類と同様に基底クラスと同様に動作します。 -
Overlap: 追跡対象のオブジェクトと重なります。
ソルバー システムを使用するには、上記のいずれかのコンポーネントを GameObject に追加します。 すべてのソルバーにはSolverHandlerが必要であるため、Unityによって自動的に作成されます。
注:
ソルバー システムの使用方法の例は、 SolverExamples.scene ファイルにあります。
追跡参照を変更する方法
SolverHandler コンポーネントの Tracked Target Type プロパティは、すべてのソルバーがアルゴリズムの計算に使用する参照ポイントを定義します。 たとえば、単純なSurfaceMagnetismコンポーネントを持つHeadの値型では、頭部からレイ キャストが発生し、どのサーフェスがヒットするかを解決するためにユーザーの視線入力の方向にキャストされます。
TrackedTargetType プロパティの潜在的な値は次のとおりです。
- *ヘッド:基準点は、メインカメラの変換です
-
ControllerRay: 参照ポイントは、ライン レイの方向を指すコントローラー上の
LinePointer変換 (つまり、モーション コントローラーまたはハンド コントローラー上のポインターの原点) です。-
TrackedHandednessプロパティを使用して、利き手設定 (つまり、左、右、両方) を選択します。
-
-
HandJoint: 参照ポイントは、特定のハンド ジョイントの変換です。
-
TrackedHandednessプロパティを使用して、利き手設定 (つまり、左、右、両方) を選択します。 -
TrackedHandJointプロパティを使用して、使用するジョイント変換を決定します
-
-
CustomOverride: 割り当てられたからの参照ポイント
TransformOverride
注:
ControllerRay 型と HandJoint 型の両方で、ソルバー ハンドラーは、前者が使用できない場合、または TrackedHandedness プロパティで指定されていない限り、最初に左のコントローラー/ハンド変換を提供し、次に右側を指定しようとします。
重要
ほとんどのソルバーは、 SolverHandlerによって提供される追跡された変換ターゲットの前方ベクトルを使用します。
ハンドジョイント追跡対象タイプを使用する場合、手のひらジョイントの前方ベクトルは、手のひらを通らずに指を通して指を指す場合があります。 これは、ハンド ジョイント データを提供するプラットフォームによって異なります。 入力シミュレーションとWindows Mixed Realityの場合、上向きベクトルは手のひらを通って上を指します (つまり、緑色のベクトルはアップ、青のベクトルは前方です)。
これを解決するには、SolverHandlerの Additional Rotation プロパティを <90、0、0> に更新します。 これにより、ソルバーに供給される前方ベクトルが手のひらを通って外側を指すようにします。
または、 コントローラー レイ 追跡ターゲット タイプを使用して、手で指すのと同様の動作を取得します。
ソルバーをチェーンする方法
複数の Solver コンポーネントを同じ GameObject に追加して、アルゴリズムをチェーンすることができます。
SolverHandler コンポーネントは、同じ GameObject 上のすべてのソルバーの更新を処理します。 既定では、 SolverHandler はスタート時に GetComponents<Solver>() を呼び出します。これにより、ソルバーはインスペクターに表示される順序で返されます。
さらに、更新されたリンク変換プロパティを true に設定すると、計算された位置、向き、スケールを、すべてのソルバー (つまり、GoalPosition) がアクセスできる中間変数に保存するようにSolver指示されます。 false の場合、 Solver は GameObject の変換を直接更新します。 変換プロパティを中間の場所に保存することで、他のソルバーは中間変数から計算を実行できます。 これは、Unityでは、gameObject.transform に対する更新が同じフレーム内のスタックに対して許可されていないためです。
注:
開発者は、 SolverHandler.Solvers プロパティを直接設定することで、ソルバーの実行順序を変更できます。
新しいソルバーを作成する方法
すべてのソルバーは、抽象基底クラス ( Solver) から継承する必要があります。 ソルバー拡張機能の主な要件は、 SolverUpdate メソッドをオーバーライドすることです。 このメソッドでは、開発者は継承された GoalPosition、 GoalRotation、 GoalScale プロパティを目的の値に更新する必要があります。 さらに、コンシューマーが望む参照フレームとして SolverHandler.TransformTarget を活用することは重要です。
次に示すコードでは、アタッチされたオブジェクトをSolverHandler.TransformTargetの前に 2 m 配置する InFront という新しいソルバー コンポーネントの例を示します。 コンシューマーはSolverHandler.TrackedTargetTypeHeadとして設定します。その後、SolverHandler.TransformTargetはカメラ変換になります。したがって、このソルバーは、アタッチされた GameObject 2 m をユーザーの視線入力の前に配置します。
/// <summary>
/// InFront solver positions an object 2m in front of the tracked transform target
/// </summary>
public class InFront : Solver
{
...
public override void SolverUpdate()
{
if (SolverHandler != null && SolverHandler.TransformTarget != null)
{
var target = SolverHandler.TransformTarget;
GoalPosition = target.position + target.forward * 2.0f;
}
}
}
ソルバー実装ガイド
一般的なソルバー プロパティ
すべてのソルバー コンポーネントには、コア ソルバーの動作を制御する同一のプロパティのコア セットがあります。
スムージングが有効になっている場合、ソルバーは、時間の経過とともに GameObject の変換を計算値に徐々に更新します。 すべての変換コンポーネントの LerpTime プロパティによって、この変更の速度が決まります。 たとえば、 MoveLerpTime の値を大きくすると、フレーム間の移動が遅くなります。
MaintainScale が有効になっている場合、ソルバーは GameObject の既定のローカル スケールを利用します。
軌道
Orbitalクラスは、太陽系の惑星のように動作するタグに沿ったコンポーネントです。 このソルバーにより、アタッチされた GameObject が追跡された変換の周りを確実に周回します。 したがって、SolverHandlerの追跡対象の種類がHeadに設定されている場合、GameObject は固定オフセットを適用してユーザーの頭の周りを周回します。
開発者は、この固定オフセットを変更して、メニューやその他のシーン コンポーネントをユーザーの視線レベルやウエスト レベルなどに維持できます。 これを行うには、[ ローカル オフセット] プロパティと [ ワールド オフセット] プロパティを変更します。 Orientation Type プロパティは、オブジェクトに適用される回転を、元の回転を維持する必要がある場合、または常にその位置を駆動している変換を行うカメラまたは面に対して適用される回転を決定します。
RadialView
RadialViewは、GameObject の特定の部分をユーザーのビューの円錐台内に保持する、もう 1 つのタグに沿ったコンポーネントです。
[最小 & 最大ビュー度] プロパティは、GameObject の一部が常に表示される必要がある量を決定します。
[最小 & 最大距離] プロパティは、GameObject をユーザーから保持する距離を決定します。 たとえば、 最小距離 が 1 m の GameObject に向かって歩くと、GameObject がプッシュされ、1 m を超えてユーザーに近づけないようにします。
一般に、 RadialView は 、追跡対象の種類 を Head に設定して、コンポーネントがユーザーの視線入力に従うために使用されます。 ただし、このコンポーネントは、追跡対象の種類の "ビュー" に保持されるように機能できます。
Follow
Follow クラスは、ローカルの前方軸を基準にして、追跡対象の前に要素を配置します。 追跡対象のターゲットがユーザー定義の境界を超えて移動するまで、要素は緩やかに制約されます ("タグア線" とも呼ばれます)。
RadialView ソルバーと同様に機能し、 最大水平 & 垂直ビューの度 と、オブジェクトの方向を変更するメカニズムを管理する追加のコントロールを使用 します。
わたって る しき
InBetween クラスは、アタッチされた GameObject を 2 つの変換の間に保持します。 GameObject 独自の SolverHandlerTracked Target Type と InBetween コンポーネントの Second Tracked Target Type プロパティは、これら 2 つの変換エンドポイントを定義します。 一般に、どちらの型も CustomOverride に設定され、結果として得られる SolverHandler.TransformOverride と InBetween.SecondTransformOverride の値は、追跡対象の 2 つのエンドポイントに設定されます。
InBetween コンポーネントは、2 番目の追跡対象の種類プロパティと Second Transform Override プロパティに基づいて、実行時に別のSolverHandler コンポーネントを作成します。
2 つの変換間の線に沿って、 PartwayOffset は、オブジェクトを中間として 0.5、最初の変換で 1.0、2 番目の変換で 0.0 を配置する場所を定義します。
SurfaceMagnetism
SurfaceMagnetismは、サーフェスの設定された LayerMask に対してレイキャストを実行し、その接触ポイントに GameObject を配置することで機能します。
Surface 法線オフセットは、サーフェス上のヒット ポイントの法線方向に、ゲーム オブジェクトの距離をサーフェスからメートル単位で配置します。
逆に、 Surface レイ オフセット では、GameObject はサーフェスからメートル単位で設定された距離を配置しますが、実行されるレイキャストの反対方向に配置されます。 したがって、レイキャストがユーザーの視線入力である場合、GameObject は、サーフェス上のヒット ポイントからカメラに沿って線の近くに移動します。
方向モードは、サーフェス上の法線に対して適用する回転の種類を決定します。
- なし - 回転が適用されていません
- TrackedTarget - オブジェクトはレイキャストを駆動する追跡された変換に直面します
- SurfaceNormal - オブジェクトは、サーフェス上のヒット ポイントでの法線に基づいて配置されます
- Blended - オブジェクトは、サーフェス上のヒット ポイントでの通常の位置に基づいて配置され、追跡された変換に対する方向に基づいて配置されます。
関連付けられている GameObject を None 以外のモードで垂直方向に維持するには、[垂直方向の 保持] を有効にします。
注:
方向モードが Blended に設定されている場合に回転係数のバランスを制御するには、OrientationBlend プロパティを使用します。 値 0.0 は TrackedTarget モードで完全に駆動される方向を持ち、値 1.0 は SurfaceNormal によって完全に駆動される方向を持つことになります。
Overlap
Overlapは、オブジェクトの変換をSolverHandler's変換ターゲットと同じ位置と回転に維持する単純なソルバーです。
ヒットできるサーフェスの決定
SurfaceMagnetism コンポーネントを GameObject に追加する場合は、コライダーがある場合は、GameObject とその子のレイヤーを考慮することが重要です。 このコンポーネントは、さまざまなレイキャストを実行して、どの表面に対して "磁石" 自体を決定するかを決定することで機能します。 ソルバー GameObject に、SurfaceMagnetism の MagneticSurfaces プロパティに一覧表示されているいずれかのレイヤーにコライダーがあるとします。 その場合、レイキャストがそれ自体にヒットし、GameObject が独自のコライダー ポイントにアタッチされる可能性があります。 この奇妙な動作は、メインの GameObject とすべての子を Ignore Ray キャスト レイヤーに設定するか、 MagneticSurfaces LayerMask 配列を適切に変更することで回避できます。
逆に、 SurfaceMagnetism GameObject は、 MagneticSurfaces プロパティにリストされていないレイヤー上のサーフェスと衝突しません。 必要なすべてのサーフェスを専用レイヤー ( サーフェス) に配置し、 MagneticSurfaces プロパティをこのレイヤーのみに設定することをお勧めします。
既定またはすべてを使用すると、UI コンポーネントまたはカーソルがソルバーに影響を受ける可能性があります。
最後に、 MaxRaycastDistance プロパティ設定より遠いサーフェスは、 SurfaceMagnetism レイキャストによって無視されます。
DirectionalIndicator
DirectionalIndicator クラスは、空間内の目的のポイントの方向に向けるタグに沿ったコンポーネントです。 最も一般的に使用されるのは、SolverHandlerの追跡対象の種類が Head に設定されている場合です。 この方法では、 DirectionalIndicator ソルバーを持つ UX コンポーネントによって、ユーザーは空間内の目的のポイントを確認するように指示されます。 このポイントは、 方向ターゲット プロパティによって決定されます。
方向ターゲットがユーザーによって表示可能な場合、または SolverHandlerで設定されている参照フレームがある場合、このソルバーは、その下にあるすべての Renderer コンポーネントを無効にします。 表示できない場合は、インジケーターですべてが有効になります。
インジケーターのサイズは、ユーザーが FOV で 方向ターゲット をキャプチャする距離が近いほど縮小されます。
最小インジケーター スケール - インジケーター オブジェクトの最小スケール
最大インジケーター スケール - インジケーター オブジェクトの最大スケール
可視性スケール係数 - 方向ターゲット ポイントが表示可能かどうかを決定する FOV を増減する乗数
ビュー オフセット - 参照フレームの視点 (つまり、カメラ) とインジケーターの方向から、このプロパティはオブジェクトがビューポートの中心からどのくらい離れているかを定義します。
方向インジケーターのシーンの例 (Assets/MRTK/Examples/Demos/Solvers/Scenes/DirectionalIndicatorSolverExample.unity)
HandConstraint と HandConstraintPalmUp のハンド メニュー
HandConstraint動作は、追跡対象のオブジェクトを手の制約付きコンテンツ (手の UI、メニューなど) に対して安全な領域に制限するソルバーを提供します。安全なリージョンは、手と交差しない領域と見なされます。
HandConstraintPalmUpと呼ばれるHandConstraintの派生クラスも含まれており、手のひらがユーザーに向いているときにソルバー追跡オブジェクトをアクティブ化する一般的な動作を示します。
ハンド 制約ソルバーを使用してハンド メニュー を作成する例については、ハンド メニューのドキュメントを参照してください。