概要
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