UnityのUIのボタンのフォーカスとフォーカス対象の設定

記事内に広告が含まれています。

UnityのUI画面を表示した時に複数のボタンがある時、キー操作やマウス操作、ゲームパッドで、選択しているボタンを変更する事が出来ますが、
マウス操作以外はあらかじめボタン1つがフォーカスされていないと他のボタンの選択が出来ません。

EventSystemに最初に選択するボタンの設定は出来ますが、ステータス画面等を開いたり閉じたりする場合最初の1回しか作用してくれません。
(Animationを使った場合はそもそもゲームオブジェクトをオン・オフするのではなくずっとある状態なので大丈夫かもしれません)

そこで画面UIを開いた時にスクリプトで決められたボタンをフォーカスするようにしてみます。

以前の記事

Unityでキーやゲームパッドで操作するステータス画面の作成
Unityでマウス、キーボードやゲームパッドで操作するステータス画面の作成をしていきます。

で、すでに同様の内容を記述してありますが、なんせ25000文字近くのボリュームの記事で、全体を通して見ないとわからないので、今回はより単純なサンプルを作成してフォーカス機能を作成してみます。

先ほどの2万文字近く&画像も多数の記事はめちゃくちゃ時間かかりましたけど、たいしてアクセスがないという悲しい結末になってしまいました(今後アクセスが増えるかもしれませんが・・・増えませんでした・・・(T_T)/~~~)

(+_+)

スポンサーリンク

今回作成するサンプルUIの説明

まずはサンプルのUIを見てみます。

画面UIのサンプル

↑が今回作成する画面UIです。

画面UIの階層

↑のような階層でCanvas(GameObjectOnOff)、Text(Title)、Panel(Background1とBackground2)とButton(それぞれ1~4)を作成してください。
Background1とBackground2にGrid Layout Groupを追加し、子要素であるButtonが整列するようにします。

レイアウトコンポーネントの追加

Background1とBackground2のパネルにAdd Component→Layout→Grid Layout Groupを追加します。

Cell SizeやSpacingでボタンの大きさと距離を指定します。

ボタンは中央に表示させたいのでChild AlignmentをMiddle Centerに設定します。

ConstraintsはFixed Column Countに設定し、Constraint Countは5に設定します。

これは列の数を5に制限してBackground1やBackground2の子要素がその数を超えた時は行を変えるようになります。

今回の場合はそれぞれのボタンが4つしかないので意味はありません・・・(最初10個ずつにしていたんですがそんなにあっても意味ないのでやめました)。

画面UIの操作について

これでサンプルのUI画面は作成出来たので、次にこの画面UIの操作を考えてみます。

今回のUI画面は画面を開いた時にBackground1のボタンのインタラクティブを全部trueにしてマウス操作やキー操作で反応するようにして、Background2のボタンのインタラクティブはfalseにし反応しないようにします。

つまり最初操作が出来るのはBackground1のボタンのみになります。

ボタンをインタラクティブにするかしないかはUI.Buttonコンポーネントを取得しプロパティのinteractableにtrueやfalseを入れると出来ます。

Background1のボタン(どれでもよい)を押したらBackground1のボタンのインタラクティブをfalseにし、Background2のボタンのインタラクティブをtrueに変更するようにします。

UIを作成した時にヒエラルキーにはEventSystemが作成されていますが、インスペクタのEventSystemのFirst Selectedには何も設定せずスクリプトから設定するようにします。

ボタンUIのinteractableを操作するActivateButtonスクリプト

それではボタンのインタラクティブに関するActivateButtonスクリプトを書いていきます。

firstSelectはBackground1とBackground2それぞれがアクティブになった時に最初にフォーカスするゲームオブジェクトをインスペクタで設定します。

ActivateOrNotActivateメソッドでは受け取った引数のbool値を自身の子要素のボタンのinteractableに設定します。

引数で受け取ったbool値がtrueだった時は最初にフォーカスする対象を設定します。

ActivateButtonスクリプトはBackground1とBackground2に設定します。

とする事で、firstSelectに指定されたゲームオブジェクトをフォーカスさせる事が出来ます。

ここでフォーカス対象を指定しない場合キー操作やゲームパッド操作が不能となってしまいます。

スクリプトの記述が終わったらBackground1とBackground2のButtonInteractableスクリプトのインスペクタのfirstSelectにそれぞれのButton(1)を設定してください。

Background1の子要素のボタン全部のButtonコンポーネントのOnClickの部分でAcitivateButtonスクリプトのActivateOrNotActivateメソッドの呼び出しを行いますが、

Background1の子要素のボタンを押した時はBackground1の子要素のボタンのinteractableをfalseにし、Background2の子要素のボタンのinteractableをtrueにする必要があります。

その為、Background1の子要素のボタンのOnClickは

Background1の子要素のボタンのOnClickの設定

↑のようにBackground1のActivateButtonのActivateOrNotActivateメソッドを呼び出し、boolはfalse、
Background2のActivateButtonのActivateOrNotActivateメソッドを呼び出し、boolはtrueを渡します。

Background2の子要素のボタンは逆になります。

ボタンイベントの設定に関しては、

Unityでスタートボタン、ゲーム終了ボタンのUIを作成する
Unityでタイトル画面を作成し、スタートボタンを押した時にゲームシーンへ遷移させ、ゲーム終了ボタンを押した時はゲームのプラットフォームに応じて処理わけする機能を作成します。

等を参照してください。

ステータス画面のオン・オフをするActivateUIObjスクリプト

最後にステータス画面のオン・オフをするスクリプトを作成します。

UnityのAnimationを使ったステータス画面のオン・オフに関しては前回の記事

ステータス画面UIのオンオフをUnityのAnimationで行う
ステータス画面UIのオンオフをUnityのAnimationで行います。UIゲームオブジェクトのオン・オフで単純に消したり登場させたり出来ますが、少しだけ演出を加えてUIを登場させてみましょう。

を参照してください。

画面UIのオン・オフスクリプトは名前をActivateUIObjとして、Main Cameraに設定します。

select1とselect2にはBackground1とBackground2のActivateButtonスクリプトを設定します。

画面を開いた時にselect1のActivateOrNotActivateにtrue、select2のActivateOrNotActivateにfalseを渡し呼び出します。

それぞれのメソッドについてはさきほど作ったので問題はないと思います。

画面UIを閉じた時は

でnullを指定しフォーカスを解除しています。

ボタンのフォーカスの機能を確認する

これでボタンをフォーカスする機能が完成したので、Unityの実行ボタンを押して確認してみましょう。

画面UIのボタンをフォーカスするサンプル

画像のサイズの問題でボタンのサイズを半分にしました。

画面UIを表示すると左側のボタンの1番目がフォーカスされ、左側のボタンのどれかを押すと左側のボタンを操作出来なくなり、右側のボタンを操作出来るようになります。

また右側のボタンが操作出来るようになったら右側の一番左のボタンがフォーカスされます。

画面UIを非表示にした後、再度表示させると左側のボタンが操作出来、一番左のボタンがフォーカスされた状態になります。

Canvas Groupコンポーネントを使ったUIの有効化・無効化

ここまででそれぞれのUI要素の有効化・無効化が出来ましたが、Background1とBackground2にAdd Component→Layout→Canvas Groupを追加すると
もっと簡単にCanvas Groupを追加したゲームオブジェクトの子要素のUIを有効化・無効化する事が出来ます。

Background1にActivateButton2を取り付けたインスペクタ

↑がBackground1にCanvas Groupとボタンの有効化・無効化&フォーカスをさせる新しいスクリプトActivateButton2を追加した状態です。

Background2も同じようになります。

Canvas Groupコンポーネントが追加されたゲームオブジェクトの子要素のUI要素はCanvas Groupの影響を受けるので、Canvas Groupのinteractableのチェックを外すと子要素であるButtonはすべて無効化されます。

Canvas Group単位でUIの有効化・無効化をするActivateButton2スクリプト

これを利用したのがActivateButton2スクリプトです。

OnEnableメソッドで自身のCanvasGroupを取得し、ActivateOrNotActivateメソッド内でCanvasGroupのinteractableを受け取った引数の値に設定します。

ボタンのOnClickの設定等は同じように設定します。

ActivateButtonのように個別のボタンの有効・無効を指定したい場合ではなく、
所属するグループ全体の有効・無効を指定したい場合はCanvas Groupコンポーネントを取りつけた方が便利ですね。

Tab(タブ)キーでフォーカスするアイテムを変更する

ブラウザ等でボタン等のUIがある場合Tabキーを使ってフォーカスするアイテムを変更する事が出来ます。

そういったキーボードでのUIの操作に慣れている人用にゲーム内でもUI要素をTabキーで変更出来ると便利です。

フォーカスするアイテムを変更するにはキーボードの矢印キーやマウスの移動等で出来ますが、これはEventSystemの
Standalone Input ModuleでHorizontal AxisとVertical AxisでHorizontalとVerticalが設定されている為に、出来るようになっています。

つまりInputManagerのHorizontalやVerticalで設定されたキー等が押された時に横や縦に移動する事になります。

その為、例えば横に移動させる時にTabキーの設定をInputManagerに作りHorizontal AxisにTab(InputManagerで設定した名前)とすれば横に移動出来るようになります。

Tabという名前でTabキーを押した時の設定を作った場合

↑のようにInputManagerにTabという名前でTabキーを押した時の設定を作り、Standalone Input Moduleの設定を変更すると横移動がTabキーで出来るようになります。

が、これだと矢印キーでの移動が出来なくなってしまうので今回は別のやり方をしたいと思います。

Standalone Input Moduleの設定は元のままにしておきます。

まずはサンプルのUIを作成します。

Panelを2つ作成し、名前をBackgroud3、Background4とします。

サンプルのBackground3とBackground4を設置したヒエラルキー

↑のようにBackground3にはボタンを3つ作成し、Background4にはToggleを2つ作成します。

Tabキー移動表示サンプルUI

↑が表示サンプルです。

Background3のインスペクタ

Background3のインスペクタは↑のようにGrid Layout Groupを設定します。
Background4にも同じように設定します。

次にボタンやトグルが選択されている時に実行するスクリプトを作成します。

ボタンやトグルが選択されている時にTabキーを押されたら次のボタンやトグルをフォーカスする為のスクリプトになります。

TabSelectedスクリプトは以下のようになります。

自身のボタンであるmySelectableをButtonと設定してしまうとトグルで使用出来なくなる為ButtonやToggleの親クラスであるSelectableを使用します。

UI要素全部の親クラスであるSelectableを使用する事によってすべてのUI要素で使えるようにしています。

SetSelectableメソッドは自身のボタンやトグルが選択されている時に呼ばれるようにするメソッドです。

イベントを発生させるのは後でやります。

SetSelectableメソッドではタブキーが押された時にボタン等のUI要素のSelectOnRightに選択されている要素をフォーカスするようにしています。

次にボタンやトグルのSelectOnRightにTabキーを押した時に選択する要素を指定していきましょう。

ButtonとToggleのNavigationをExplicitにします。

Button1のSelectOnRightにはButton2
Button2のSelectOnRightにはButton3
Button3のSelectOnRightにはToggle1

をドラッグ&ドロップしていってください。

またそれぞれのボタンとトグルにAdd Component→Event→Event Triggerを追加し、Add New Event Typeをクリックして、UpdateSelectedを選択します。

UpdateSelectedイベントはそのボタンやトグル等が選択されている時に常に呼ばれるUpdateメソッド的なものです。

ゲームオブジェクトにはそれぞれのボタンやトグル自身をドラッグ&ドロップし、呼び出すメソッドはTabSelectedスクリプトのSetSelectableメソッドを設定します。

ボタン1に設定を施した後のインスペクタ

Button1は↑のように設定します。
他のボタン等も設定してください。

最後にEventSystemのFirst SelectedにButton1をドラッグ&ドロップし最初にButton1が選択されるようにしておきます。

これで設定が完了しました。

Unityの実行ボタンを押して確認してみましょう。

Tabキーでフォーカスを変更するサンプル動画

Tabキーでフォーカス対象が変わるようになりました。
(^^)v

Shiftキー+Tabキーで逆方向にフォーカスする

WebブラウザではTabキーを押すと右→下という流れでフォーカスが進みますが、Shiftキーを押しながらTabキーを押すと左→上という風に逆方向にフォーカス対象が変わります。

そこでボタンやトグルのSelectOnLeftに反対側のボタンやトグルを設定し、TabSelectedでShiftキーの検知も行いShift+Tabを押した時に逆向きにフォーカスしていくようにしたいと思います。

Tabキーだけの判定条件はShift+Tabの条件より後に行います。

シフトキーが押されているかどうかは左右のどちらかが押されていればOKです。

ただInput.GetButtonDownだと押された時の1フレームしか検知出来ないのでInput.GetKeyを使います。

Input.GetKeyは押されている間ずっとtrueになります。

Shift+Tabキーの検知が出来た時は、SelectOnLeftに指定されているUIの要素にフォーカスを当てるようにします。

Shift+Tabキーで逆方向にフォーカスしていくサンプル

これでShift+Tabキーで逆方向への移動も可能となりました。

今回のボタンのフォーカスの記事を書いた理由

これでUnityのUIでボタンのフォーカスとフォーカス対象の設定が出来るようになりました。
(UnityのAnimationでPanelのScaleだけを操作している場合はまた別の対処が必要になります)

キーやゲームパッド等で選択しているボタンを変更すると、たまにフォーカスされてない!?なんて事があります。

そんな時は別のUIを作成していてそのボタンのUI等(ボタン以外のUIでもフォーカス出来るものがあります)がフォーカスされてしまっているという事もあります。

今回この記事を書いたのは

Unityでキーやゲームパッドで操作するステータス画面の作成
Unityでマウス、キーボードやゲームパッドで操作するステータス画面の作成をしていきます。

の記事で今回と同じようにボタンのinteractableを操作していた時にボタンがフォーカスされているはずなのに、ボタンがHighlight表示にならなくて
ボタンを継承してその問題に対処していた部分を抽出して取り上げようと思ったんですが、今回はそれが発生しませんでした・・・・(^_^;)

正直なところその記事の内容もだいぶ忘れているので、どんな状況下で起きた現象か忘れてしまったんですよね・・・。

不具合を発生させる事が出来ないので、今回はボタンのフォーカスのみの記事となりました・・・・。
(-.-)

タイトルとURLをコピーしました