日本語翻訳ドキュメントはサポートを終了しました

MRTK 2.6 以降のドキュメントについては、公式の Microsoft ドキュメント を参照してください。

    Show / Hide Table of Contents

    Solvers (ソルバー)

    Solver

    Solvers(ソルバー) は、事前に定義されたアルゴリズムにしたがってオブジェクトの位置と回転の計算方法を容易にするコンポーネントです。一つの例として、ユーザーのゲイズ レイキャストが現在当たっている面にオブジェクトをを配置するということが挙げられます。

    さらに、Unity にはコンポーネントの update 順を指定するための信頼できる方法はありませんが、ソルバー システムはこれらの移動の計算順序を確定的に定義しています。

    ソルバーは、オブジェクトを他のオブジェクトやシステムにくっつけるための幅広い振る舞いを提供しています。他の例として、(カメラを基準として)ユーザーの前に浮かぶタグアロング オブジェクトがあります。ソルバーはオブジェクトをコントローラーに追従させるために、コントローラーとオブジェクトにアタッチすることもできます。全てのソルバーは安全に積み重ねることができます。例えば、タグアロング + surface magnetism + momentum と組み合わせられます。

    Solver (ソルバー) の使い方

    ソルバー システムは、3つのカテゴリーのスクリプトから構成されています:

    • Solver: 全てのソルバーが継承する、ベースとなる abstract class です。状態トラッキング、スムーズにするためのパラメーターと実装、自動的なソルバー システムの統合、そしてアップデート順序を提供しています。
    • SolverHandler: 追跡する参照オブジェクト (例えば、メイン カメラのトランスフォーム、ハンド レイなど) を設定し、ソルバー コンポーネントを集めて適切な順序で更新を実行します。

    3つめのカテゴリーはソルバー自身です。以下のソルバーは、基本的な動作のためのビルディング ブロックを提供しています。

    • Orbital: 参照オブジェクトから、指定された位置とオフセットを持った場所に固定します。
    • ConstantViewSize: 参照オブジェクトから見て、一定のサイズを保つように大きさを変えます。
    • RadialView: 参照オブジェクトからみて、オブジェクトが視野の中に入るようにします。
    • SurfaceMagnetism: ワールドの面にレイを飛ばし、オブジェクトをその面に合わせます。
    • Momentum: 他のソルバーやコンポーネントによって動かされるオブジェクトに対して、運動量や弾性をシミュレーションするために、加速度、速度、摩擦を適用します。
    • InBetween: オブジェクトが2つのトラックされたオブジェクトの間にあるように保ちます。
    • HandConstraint: オブジェクトが、ハンドと交差しない領域内でハンドを追従するように制約します。メニューなどの、ハンドに拘束されたインタラクティブなコンテンツに便利です。このソルバーは IMixedRealityHand とともに動作するよう意図されていますが、IMixedRealityController とも動作します。
    • HandConstraintPalmUp: HandConstraint から派生していますが、有効化の前に手のひらがユーザーを向いているかをテストするロジックが含まれています。このソルバーは IMixedRealityHand コントローラーでのみ動作し、他のコントローラー タイプについては、このソルバーは基底クラスと全く同じ動作をします。

    ソルバー システムを使うためには、上記コンポーネントの一つをゲームオブジェクトに単に追加するだけです。全てのソルバーは SolverHandler を必要とするため、SolverHandler は Unity によって自動的に作成されます。

    Note

    ソルバー システムの使い方の例は、SolverExamples.scene ファイルにて見つけることができます。

    追跡参照を変更する方法

    SolverHandler コンポーネントの Tracked Target Type プロパティは、全てのソルバーがアルゴリズムを計算するときに使用する参照点を定義します。例えば、シンプルな SurfaceMagnetism コンポーネントとともに Head が指定された場合、頭からユーザーのゲイズ方向へのレイキャストが、どの面にヒットするかを解決するために使われます。TrackedTargetType プロパティに設定可能な値は以下の通りです。

    • Head : 参照点はメイン カメラのトランスフォーム
    • ControllerRay: 参照点は、ライン レイの方向を指しているコントローラーの LinePointer のトランスフォーム(すなわち、モーション コントローラーやハンド コントローラーのポインター原点)。
      • どちらの手(左手、右手、両手)を優先するかを選択するには、TrackedHandedness プロパティを使用します。
    • HandJoint: 参照点は特定のハンド ジョイントのトランスフォーム
      • どちらの手(左手、右手、両手)を優先するかを選択するには、TrackedHandedness プロパティを使用します。
      • 利用するジョイントのトランスフォームを決定するには、TrackedHandJoint プロパティを使用します。
    • CustomOverride: アサインされた TransformOverride からの参照点
    Note

    ControllerRay と HandJoint タイプの両方について、TrackedHandedness プロパティが Both の場合、ソルバー ハンドラーは左のコントローラー/ハンドのトランスフォームを提供しようとし、左が利用できなければ右の値を提供しようとします。

    Solver
    TrackedTargetType に関連するさまざまなプロパティの例

    Important

    多くのソルバーは SolverHandler によって提供される tracked transform target (追跡するトランスフォーム ターゲット) の forward vector を使用します。Hand Joint のターゲット追跡タイプを使うとき、手のひらのジョイントの forward vector は手のひらをつき抜ける方向ではなく、指の方向を向くかもしれません。これは、プラットフォームが提供する手のジョイント データによります。入力シミュレーションと Windows Mixed Reality では、up vector が手のひらをつき抜ける向き (緑色の vectorが up, 青色の vector が forward) です。

    Solver

    これを解決するため、SolverHandler の Additional Rotation プロパティを <90, 0, 0> に更新します。これにより、ソルバーに提供される forward ベクターが手のひらをつき抜けて手の外側へと向くようになります。

    Solver

    あるいは、Controller Ray のターゲット追跡タイプを使うことで、似たようなふるまいをさせることもできます。

    Solver (ソルバー) を連鎖させる方法

    複数の Solver コンポーネントを同じゲームオブジェクトに追加し、アルゴリズムを連鎖させることが可能です。SolverHandler コンポーネントは、同じゲームオブジェクト上のすべてのソルバーの更新を取り扱います。デフォルトでは SolverHandler は Start で GetComponents<Solver>() を呼び出し、これはインスペクターで表示される順序でソルバーを返します。 さらに、Updated Linked Transform プロパティを true に設定すると、Solver は計算した位置、姿勢、スケールをすべてのソルバー(すなわち、 GoalPosition)からアクセスできる仲介変数に保存します。false の場合は、Solver はゲームオブジェクトのトランスフォームを直接更新します。トランスフォームのプロパティを仲介の場所に保存すると、他のソルバーがその仲介変数から計算を始めることができます。この理由は、Unity は gameObject.transform を同じフレーム内にスタックして更新することを許容していないからです。

    Note

    開発者は、SolverHandler.Solvers プロパティを直接設定することでソルバーの実行順序を変更することができます。

    新しい Solver (ソルバー) の作り方

    すべてのソルバーは抽象基底クラスである Solver を継承しなければなりません。Solver の拡張に主に必要となるのは、SolverUpdate メソッドのオーバーライドに関するものです。このメソッドで、開発者は継承された GoalPosition、GoalRotation、GoalScale プロパティを望ましい値に更新すべきです。さらに、SolverHandler.TransformTarget を、利用者が望む参照座標系として利用すると、たいていの場合に役に立つでしょう。

    以下のコードは、InFront という新しいソルバー コンポーネントの例です。これは、アタッチされたオブジェクトを SolverHandler.TransformTarget の前 2m の位置に配置します。もし、SolverHandler.TrackedTargetType が Head に設定された場合、SolverHandler.TransformTarget はカメラのトランスフォームとなり、このソルバーはすべてのフレームでアタッチされたゲームオブジェクトユーザーのゲイズの前 2m の位置に配置します。

    /// <summary>
    /// InFront ソルバーは追跡されるトランスフォーム ターゲットの前 2 m の位置にオブジェクトを配置します
    /// </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;
            }
        }
    }
    

    Solver implementation guides

    Common Solver properties

    Every Solver component has a core-set of identical properties that control the core Solver behavior.

    If Smoothing is enabled, then the Solver will gradually update the transform of the GameObject over time to the calculated values. The speed of this change is determined by every transform component's LerpTime property. For example, a higher MoveLerpTime value will result in slower increments in movement between frames.

    If MaintainScale is enabled, then the Solver will utilize the GameObject's default local scale.

    Core Solver Properties
    Common properties inherited by all Solver components

    Orbital

    The Orbital class is a tag-along component that behaves like planets in a solar system. This Solver will ensure the attached GameObject orbits around the tracked transform. Thus, if the Tracked Target Type of the SolverHandler is set to Head, then the GameObject will orbit around the user's head with a fixed offset applied.

    Developers can modify this fixed offset to keep menus or other scene components at eye-level or at waist level etc. around a user. This is done by modifying the Local Offset and World Offset properties. The Orientation Type property determines the rotation applied to the object if it should maintain it's original rotation or always face the camera or face whatever transform is driving it's position etc.

    Orbital Example
    Orbital example

    RadialView

    The RadialView is another tag-along component that keeps a particular portion of a GameObject within the frustum of the user's view.

    The Min & Max View Degrees properties determines how large of a portion of the GameObject must always be in view.

    The Min & Max Distance properties determines how far the GameObject should be kept from the user. For example, walking towards the GameObject with a Min Distance of 1m will push the GameObject away to ensure it is never closer than 1m to the user.

    Generally, the RadialView is used in conjunction with Tracked Target Type set to Head so that the component follows the user's gaze. However, this component can function to be kept in "view" of any Tracked Target Type.

    RadialView Example
    RadialView example

    InBetween

    The InBetween class will keep the attached GameObject between two transforms. These two transform endpoints are defined by the GameObject's own SolverHandler Tracked Target Type and the InBetween component's Second Tracked Target Type property. Generally, both types will be set to CustomOverride and the resulting SolverHandler.TransformOverride and InBetween.SecondTransformOverride values set to the two tracked endpoints.

    At runtime, the InBetween component will create another SolverHandler component based on the Second Tracked Target Type and Second Transform Override properties.

    The PartwayOffset defines where along the line between two transforms the object shall be placed with 0.5 as halfway, 1.0 at the first transform, and 0.0 at the second transform.

    InBetween Example
    Example of using InBetween solver to keep object between two transforms

    SurfaceMagnetism

    The SurfaceMagnetism works by performing a raycast against a set LayerMask of surfaces and placing the GameObject at that point of contact.

    The Surface Normal Offset will place the GameObject a set distance in meters away from the surface in the direction of the normal at the hit point on the surface.

    Conversely, the Surface Ray Offset will place the GameObject a set distance in meters away from the surface but in the opposite direction of the raycast performed. Thus, if the raycast is the user's gaze, then the GameObject will move closer along the line from the hit point on the surface to the camera.

    The Orientation Mode determines the type of rotation to apply in relation to the normal on the surface.

    • None - No rotation applied
    • TrackedTarget - Object will face the tracked transform driving the raycast
    • SurfaceNormal - Object will align based on normal at hit point on surface
    • Blended - Object will align based on normal at hit point on surface AND based on facing the tracked transform.

    To force the associated GameObject to stay vertical in any mode other than None, enable Keep Orientation Vertical.

    Note

    Use the Orientation Blend property to control the balance between rotation factors when Orientation Mode is set to Blended. A value of 0.0 will have orientation entirely driven by TrackedTarget mode and a value of 1.0 will have orientation driven entirely by SurfaceNormal.

    SurfaceMagnetism Example

    Determining what surfaces can be hit

    When adding a SurfaceMagnetism component to a GameObject, it is important to consider the layer of the GameObject and it's children, if any have colliders. The component works by performing various types of raycasts to determine what surface to "magnet" itself against. If the solver GameObject has a collider on one of the layers listed in the MagneticSurfaces property of SurfaceMagnetism, then the raycast will likely hit itself resulting in the GameObject attaching to it's own collider point. This odd behavior can be avoided by setting the main GameObject and all children to the Ignore Raycast layer or modifying the MagneticSurfaces LayerMask array appropriately.

    Conversely, a SurfaceMagnetism GameObject will not collide with surfaces on a layer not listed in the MagneticSurfaces property. It is generally recommended to place all desired surfaces on a dedicated layer (i.e Surfaces) and setting the MagneticSurfaces property to just this layer. Using default or everything may result in UI components or cursors contributing to the solver.

    Finally, surfaces farther than the MaxRaycastDistance property setting will be ignored by the SurfaceMagnetism raycasts.

    Hand Menu with HandConstraint and HandConstraintPalmUp

    Hand Menu UX Example

    The HandConstraint behavior provides a solver that constrains the tracked object to a region safe for hand constrained content (such as hand UI, menus, etc). Safe regions are considered areas that don't intersect with the hand. A derived class of HandConstraint called HandConstraintPalmUp is also included to demonstrate a common behavior of activating the solver tracked object when the palm is facing the user.

    Please see Hand Menu page for the examples of using Hand Constraint solver to create hand menus.

    Experimental Solvers

    These solvers are available in MRTK but are currently experimental. Their APIs and functionality are subject to change. Furthermore, their robustness and quality may be lower than standard features.

    Directional Indicator

    The DirectionalIndicator class is a tag-along component that orients itself to the direction of a desired point in space.

    Most commonly used when the Tracked Target Type of the SolverHandler is set to Head. In this fashion, a UX component with the DirectionalIndicator solver will direct a user to look at the desired point in space.

    The desired point in space is determined via the Directional Target property.

    If the directional target is viewable by the user, or whatever frame of reference is set in the SolverHandler, then this solver will disable all Renderer components underneath it. If not viewable, then everything will be enabled on the indicator.

    • Visibility Scale Factor - Multiplier to increase or decrease the FOV that determines if the Directional Target point is viewable or not
    • View Offset - From the viewpoint of the frame of reference (i.e camera possibly), this property defines how far in the indicator direction should the object be from the center of the viewport.

    Directional Indicator properties
    Directional Indicator properties

    Directional Indicator example scene

    Directional Indicator Example Scene (Assets/MRTK/Examples/Experimental/Solvers/DirectionalIndicatorExample.unity)

    See also

    • Hand Tracking
    • Gaze
    • Improve this Doc
    Back to top Generated by DocFX