概要
MRTKは色々な機能が用意されていて本当~に便利なのですが、『「◯◯がしたい!」という目的に対して「MRTKのどの機能がどう使えるのか」が分からない』というのが往々にしてぶつかる壁ではないかなと思います。
本記事ではMRTKで最も使うであろうボタンについて、コンポーネント構成と設定を(分かる範囲で)解説します。
公式ドキュメントと併せて読んで理解を深めていきましょう。
環境
Oculus Quest 2でMRTKを使います。([導入方法はこちら]
(https://microsoft.github.io/MixedRealityToolkit-Unity/Documentation/CrossPlatform/OculusQuestMRTK.html))
- Unity 2019.4.16f1
- MRTK v2.5.1(Package Manager)
ボタンの作り方
MRTKでボタンを作るには、MRTK Toolboxを使うのが手っ取り早いです。
基本的なUIオブジェクトがまとめられており、ワンクリックでオブジェクトをシーンに配置できます。


今回はこちらの「Hololens2 Button 32x32mm」を使います。まずはシーンに配置して、エディタで動作確認しやすいように(0, 0, 0.2)の位置に移動させておきます。

ボタンを構成するコンポーネントたち
このボタンを構成するコンポーネントは以下の通り。(記事内リンク)
- Transform
- Box Collider
- PressableButtonHololens2
- PhysicalPressEventRouter
- Interactable
- Audio Source
- NearInteractionTouchable
- Button Config Helper
ひとつずつ見ていきましょう。
Transform コンポーネント
言わずと知れた、オブジェクトの位置、回転、スケールを扱うクラスです。
Scene内の全てのオブジェクトは必ずTransformコンポーネントを持ちます。
エディタで動作確認しやすいように(0, 0, 0.2)の位置に移動させておきます。
MRTKには入力シミュレート機能があり、Gameビューを右ドラッグしてポインターを動かし、右クリックでインタラクションできます。(GGVインタラクション)
前章でボタンのZ軸の位置を変えたのは、あらかじめGameビューでボタンが見えるように配置することで、このシミュレートをしやすくする意図があります。

Box Collider コンポーネント
ボタンの当たり判定です。これを非アクティブにするとポインターと指で触れても何も反応しなくなります。ボタンには必須です。
「じゃあボタンを押させたくない時はenabled = falseすればいいんだな」と思いますよね?それはそうなんですけれども、もっといい方法があります。後述。

ちなみにボタンが押されるとBoxColliderも動くのかというとそうではなく、ボタンが押されてもBoxColliderは微動だにしません。
PressableButtonHololens2 コンポーネント
このコンポーネントを展開すると、Gizmoで水色、赤色、黄色、青色の平面が表示されます。これはこのコンポーネントの設定を可視化したものです。

それぞれが何を意味しているのか見ていきましょう。
Moving button Visuals
GameObject型のSerializeFieldで、ButtonContentというオブジェクトがアタッチされています。
Toolboxから出した状態ではButtonContentオブジェクトはただの空のGameObjectです。

ボタンを押したときに動いてほしいオブジェクトをここに指定してあげると良さそうです。
Start Push Distance
読んで字のごとく、「ボタンを押したと判断する面」がボタン中心からどれだけ離れているかの距離です。
Gizmoでは水色の面で表現され、これに触れるとTouch Beginイベントが発生します。
Max Push Distance
ボタンを押したときにMovingButtonVisualsのオブジェクトが動く最大距離です。
Gizmoの青い面で表現され、これが負の数値だとTouch Begin Touch Endイベントは発生しても、Button Press Button Releaseイベントが発生しなくなります。正の数値にしておきましょう。
Press Distance
「ボタンが押された」とみなすまでの距離です。Touch Beginイベント後、Button Pressedイベントが発生するまでの押し込み量とも言えるでしょう。Gizmoの黄色い面です。
これを大きめにすることで、いわゆる「軽く触っただけでは反応せず、深く押し込まないといけないボタン」になるでしょう。
Release Distance Delta
Button Pressedイベント後、どのくらいボタンから指を離せばButton Releasedイベントが発生するかの距離です。Gizmoの赤い面で表現されています。
Return Speed
ボタンから指を離したのち、Moving button Visualsのオブジェクトが元の位置に戻る際の速さです。
数値が小さいほど、ゆっくり戻ります。
Release On Touch End
通常、イベントはTouch Begin→ Button Pressed→ Button Released→ Touch Endの流れで起こりますが、処理落ちなどによってButton Releaseイベントが発生し損ねるかもしれません。このフラグがセットされていると、その場合にもTouch EndイベントでButton Releaseイベントを発生させるようになります。
つまり、Button Releasedイベントの発生保証と言えるでしょう。
Enforce Front Push
ボタンが前からしか押せないようにします。
Events
このボタンのイベントです。
Button PressedおよびButton Releasedイベントで音を発生させる他、各イベントでPhysicalPressEventRouterコンポーネントのメソッドも呼んでいるようです。(後で詳しく解説します)
この部分は、Unityの標準GUIのボタンと同じように、任意のメソッド呼び出しを登録できるようになっています。

Moving Button Icon Text
ボタンを押したときに連動して動く、ボタンのアイコンやテキストのオブジェクトを指定します。
Moving button Visualsで押したときに動いてほしいオブジェクトを指定していましたが、アイコンやテキストはそれとは別で指定できるようになっているようです。
こちらはボタンを押したときにMoving button Visualsオブジェクトの移動量の半分だけ動くようになっています。(アイコンや文字が激しく動きすぎないようにしている?)

Compressable Button Visuals
ボタンを押したときに潰れるオブジェクトです。同名のGameObjectがあり、輪郭だけ描画するマテリアルをつけたFrontPlateというCubeと、指を近づけたときに光るHighlightPlateというQuadで構成されています。

Moving button Visualsは単純に移動するだけですが、こちらは押した動きに連動してZ軸に伸縮します。

Min Compress Percentage
ボタンを押しきったときに、Compressable Button Visualsで指定したオブジェクトが元の何パーセントまで潰れるかを設定できます。↑のGIFでZ軸のスケールが0.25~1で変化しているのが見てわかるでしょうか。
ちなみに'Percentage'とありますが、最大値は1です。
Highlight Plate
ボタンにフォーカスしたときにハイライトする部分を指定します。
Compressable Button Visualsに指定したオブジェクトの子にあるHighlightPlateオブジェクトがアタッチされています。

Highlight Plate Animation Time
フォーカスしたときにのハイライト表現を、何秒かけて行うかの設定です。
Button State
これはボタンの状態確認用の表示です。
- Current Push Distance:ボタンをどのくらい押しているのか
- Touching:ボタンに触れているか
- Pressing:ボタンを押しているか
Editor Settings
エディタの設定です。
- Show Button Event Planes
Moving button Visualsなどの設定をGizmoで可視化するか - Make Planes Editable
Moving button Visualsなどの設定をドラッグでできるようにするか(有効にすると、Sceneビューで面の端をドラッグして調整できるようになります)
PhysicalPressEventRouter コンポーネント

このボタンにおけるPhysicalPressEventRouterコンポーネントの役割は、PressableButtonHololens2コンポーネントと、後述するInteractableコンポーネントの橋渡しをすることです。
Routing Target
PressableButtonHololens2コンポーネントに連動させるInteractableコンポーネントを指定します。
Interactable On Click
PressableButtonHololens2のどのイベントをInteractableコンポーネントのOn Clickイベント発生のトリガーにするかを選択できます。
- Event On Click Completion
PressableButtonHololens2のButton Releasedイベント(ボタンを押して、離す)をトリガーにします。 - Event On Press
PressableButtonHololens2のButton Pressedイベント(ボタンを押す)をトリガーにします。 - Event On Touch
PressableButtonHololens2のTouch Beginイベント(ボタンに触れる)をトリガーにします。
Interactable コンポーネント
Interactableコンポーネントは、あらゆるオブジェクトをインタラクション可能にする、オールインワンなコンポーネントです。
公式ドキュメントがかなり詳しくまとまっていますので、必読です。

Inspectorは大きく3つのセクション(General, Profiles, Events)に分かれています。
それぞれ見ていきましょう。
General セクション
States
ボタンがどんな状態を持つかを定義されている、ScriptableObjectです。
このボタンだとFocusPressTouchGrabStatesがアタッチされていますが、その中身は下図の通り。Pressed、Disabledなど、たくさん種類が定義されています。ここに定義されている7種類の状態を、このボタンが取りうるということが分かります。

Enabled
このボタンが有効かどうかのフラグです。コード上ではInteractable.IsEnabledでアクセスできます。
「じゃあボタンを押させたくない時はenabled = falseすればいいんだな」と思いますよね?それはそうなんですけれども、もっといい方法があります。
ボタンをただ無効にしたいときはInteractable.IsEnabled = falseを使いましょう。
MonoBehaviour.enabled = falseをしたときはクラス内の全てが無効化されますが、Interactable.IsEnabled = falseを使うと、基本的な見た目の更新を維持しつつ、On Pres入力のみ無効化し、Disabledステート(前述のStatesの一種)に移行させることができます。
これとビジュアルテーマ(後述)を使うと、例えば「無効化したボタンは背景を暗くして、押せないことが一目見てわかるようにする」ような表現が簡単にできるようになります。
Input Actions
このボタンがどんな入力に反応するかの設定でで、このボタンではSelectが設定されています。
このSelectとは、MixedRealityToolkit > Input > Input Actionsで定義されたActionです。

MixedRealityToolkit > Input > Gesturesで、タップ操作をSelectに紐付けています。要するに、タップすればSelect入力になるようになっています。

Is Global
Input Actionsでどんな入力に反応するか設定してありますが、Is Globalはその入力がこのオブジェクトに対して行われていなくても入力を受け取るようにする設定です。
このボタンで例えると、Is Globalが有効ならシーン内のどこをエアタップしてもボタンが反応するようになります。(あまり使うことはない設定かも)
Speech Command
Input Actionsではどんな入力に反応するか設定しましたが、こちらはどんな音声入力に反応するかを設定できます。
「Select」と発声することで、このボタンにインタラクションできるということです。
音声入力の設定はMixedRealityToolkit > Input > Speechにあります。
この設定のドキュメントはこちら。

Require Forcus
フォーカスしたときにのみ音声入力を受け付けるかの設定です。これがTrueであるということは、ポインターなどでボタンにフォーカスした上で「Select」と発声することでインタラクション可能だということになります。
Speech Command版、Is Global設定と言えるでしょう。(フラグのつけ方は逆ですが)
Selection Mode
このボタンがどんなボタンなのかの設定です。
- Button:ただのボタンです。このボタンではこちらが選択されています。
- Toggle:トグルボタンです。On/Offの二つの状態を持ちます。
- Multi Dimension:複数の状態を持つボタンです。
Profiles セクション
Profilesは、インタラクションによって起こるStateの変化に対して、どんなビジュアルの変更をするかを設定できます。
Reset On Destroy
このコンポーネントが削除された時、変更した内容を元に戻すかどうかの設定です。
Target
ビジュアルの変更をするGameObjectを指定します。
Theme
ビジュアルの変更内容について定義したTheme型のScriptableObjectを指定します。
設定済みのビジュアルテーマの解説1:SeeItSayItLabel
このボタンにあらかじめ設定されているProfilesを解説していきます。
まずはHolographicButtonSeeItSayItLabelテーマから。

ざっくり言うと、ここで設定している動作は以下のような感じです。
- Stateが
Focusになったときに、SeeItSayItLabelオブジェクトのScaleを(1, 1, 1)にする動作を開始する(赤枠) -
Duration秒後(1秒後)にこの動作を完了する(黄枠) - ジャスト
Duration秒に到達するまでScaleは変化させない(黄枠)
実際に、ボタンにフォーカスした1秒後に「SeeItSayItLabel」オブジェクトのScaleが変化しているのが分かるでしょうか。
この動きは、ユーザーに「このボタンは音声でインタラクションできるよ」というのを伝える目的がありそうです。

設定済みのビジュアルテーマの解説2:FrontPlate
もうお分かりですね?このProfileの動作は以下のようなものです。
- Stateが
Pressedになったとき、FrontPlateオブジェクトをZ軸に0.008m動かす - 0.03秒かけて、ゆっくりと変化を適用する
[Compressable Button Visuals](#Compressable Button Visuals)で、押したボタンがZ軸に伸縮するのは説明しましたが、単純にポインターを使ったときはその動きはありません。そのときにボタンの挙動が不自然にならないように、ここでポインターでボタンを押したときの動きを定義しているようです。
設定済みのビジュアルテーマの解説3:UIButtonSquareIcon
最後にPressableButtonIconテーマです。テーマ名からして、汎用的にボタンに使うことを想定していそうです。

このテーマは、FocusとPhysicalTouchで異なる動きをするようになっています。
- Stateが
Focusになったとき、UIButtonSquareIconオブジェクトをZ軸に-0.002m動かす - Stateが
PhysicalTouchになったとき、UIButtonSquareIconオブジェクトをZ軸に-0.0005m動かす - 瞬時に変更を適用する(
Easingを使用しない)
Events セクション
Unity標準GUIでおなじみのOn Clickイベントにメソッドを登録できます。

Receivers
Receiversを展開すると、さらに細かくフォーカス時などのイベントにメソッドを登録できます。
登録されているメソッド群を見ると、ボタンにフォーカスしたときにボタン表面にハイライトが入るようにしている他、ボタンを押したときに音を鳴らしています。

しかし、ボタンを押したときに音を鳴らすのは、PressableButtonHololens2コンポーネントのイベントでもやっていました。これは同じことを二重にやっているのではなく、PressableButtonHololens2の方ではNear Interaction(指で押すなどの近接的な入力)、Interactableの方ではFar Interaction(ポインター&エアタップなどの遠距離からの入力)のPressイベントに対応させているのです。
Interaction Filter

On Press系のReceiverを扱うときのみ、それがFar InteractionなのかNear Interactionなのかをフィルタリングできます。
しかし、ボタンを押したときに音を鳴らすのは、
PressableButtonHololens2コンポーネントのイベントでもやっていました。これは同じことを二重にやっているのではなく、PressableButtonHololens2の方ではNear Interaction(指で押すなどの近接的な入力)、Interactableの方ではFar Interaction(ポインター&エアタップなどの遠距離からの入力)のPressイベントに対応させているのです。
「これをNear And Farすればイベント登録が一回で済むじゃん」というのはそうなのですが、わざわざFar Onlyにして別々にイベント登録しているのは、PressableButtonHololens2の方ではボタンを背面から押せないようにするEnforce Front Pushという設定がありましたが、Interactableにはその区別がなく、背面からでもOnPressイベントが発生してしまうからだと思われます。(より現実的な動きに準ずるためにこのようにしている?)
Audio Source コンポーネント
音の発生源となるコンポーネントです。このボタンでは、ボタンを押したときに音を出すのに使用しています。
AudioSouceコンポーネントを大量に配置するのは負荷的によろしくないので、ある程度数が多くなってきたら、効果音発生用のAudioSourceを用意して統括的に音を出した方がいいかも知れません。
参考:【Unite Tokyo 2018】Audio機能の基礎と実装テクニック
NearInteractionTouchable コンポーネント
Near Interaction(指で押すなどの近接的な入力)をするために必須のコンポーネントです。
実際にこのコンポーネントがついていないと、PressableButtonHololens2コンポーネントに警告が表示されます。
警告に従ってボタンをポチポチ押せばパラメータを設定してくれるので、特に設定で困ることはありません。


例えばLocal Forwardはボタンの向きの設定で、PressableButtonHololens2の前からのみボタンを押せるようにする設定に使われたりします。
Button Config Helper コンポーネント
最後のコンポーネント、ButtonConfigHelperはMRTK v2.4で追加されました。
名前の通り、ボタン名やイベント登録、アイコン設定などを補助してくれます。
Labels,Basic Events,Iconのセクションに分かれており、Show Component Referencesを有効にすることで、実際に紐付けられているオブジェクトのSerializeFieldが見えるようになります。

Labels セクション
ボタンのテキストをここでまとめて変更できます。Enable *のチェックを外せば、そのオブジェクトを非アクティブにできます。

Basic Events セクション
ここにイベントを登録すれば、InteractableコンポーネントのOn Clickイベントに登録されます。登録を解除すれば、Interactableの方でも登録解除されます。便利!

Icon セクション
ボタンのアイコンを変更できます。
既定のアイコンから選べるほか、任意のフォントを追加して使うことができるようです。

参考:MRTKでボタンのアイコンセット(IconSet)を作成してアイコンの見た目を変更する
以上でこのボタンの解説は終了です。(長かった...)
参考
- Button (ボタン) | Mixed Reality Toolkit Documentation
- 入力シミュレーション サービス (Input Simulation Service) | Mixed Reality Toolkit Documentation
- Speech (音声) | Mixed Reality Toolkit Documentation
- Interactable (インタラクタブル) | Mixed Reality Toolkit Documentation
- Visual themes | Mixed Reality Toolkit Documentation
- Class PhysicalPressEventRouter | Mixed Reality Toolkit Documentation
- MRTKでボタンのアイコンセット(IconSet)を作成してアイコンの見た目を変更する
- 【Unite Tokyo 2018】Audio機能の基礎と実装テクニック
- MRTK Standard Shader | Mixed Reality Toolkit Documentation




