
ゲームパッドのみでUnityのUIを操作したい
バグと初期選択ボタンの問題
開発中の「Momi」は卒業制作展に合わせて制作していたこともあってゲームパッドorキーボードを前提に作ってきました。しかしまあ情報が少なく無理矢理実装したらよく分からないバグが発生しました。
この記事はバグ潰しついでに卒展時点で実装出来なかった分のメニュー拡張を行った際、直面した問題の対処記録です。
発生していたバグと原因
2022/02/21-23で確認していた「Momi」のバグです。
①特定Sceneのみメニュー画面が表示できない
Consoleの表示:EventSystem.current.SetSelectedGameObject()の中身が無い。
nullreferenceexception オブジェクト参照がオブジェクト インスタンスに設定されていません。
②複数パネルの表示切替が出来ない
Consoleの表示:Inspecter上でスクリプトの変数が割り当てられていない。
UnassignedReferenceException: The variable sabPanel of MainUIController has not been assigned.
You probably need to assign the sabPanel variable of the MainUIController script in the inspector.
結論から言えばPrefab化して使用していたCanvasをScene側で弄っていたのが原因です。メニュー表示が出来ないSceneはPrefabの設定が反映されていたためInspecter上の変数が全く入力されておらず、結果的にNullを吐いていました。
ボタン処理を行うScriptを同じPrefabに格納する
今回対処した方法です。
①全てのSceneで既存のCanvasを削除、Prefab化Canvasに置き換え
②Prefab内にボタンに関する処理を行うGameObjectを格納
③Prefab内でInspecter上の変数を全て割り当てる


終わってみれば割と初歩的なミスが招いたバグでしたね…。
ゲームパッドのみでUnityのUIを操作する方法
初期選択ボタンの問題
ようやく本題。とは言えこちらの問題は日本語情報が少ないだけで割とすぐ見つかりました。
Canvas作成時に一緒についてくるEventSystemのInspecter上で初期選択ボタンが設定できるのは前回記事にしました。しかしこの方法ではメニュー内で複数のパネルを行き来する場合、機能してくれません。

結局のところ、スクリプトで制御が必要となるわけです。
解決方法としてはパネルを切り替える度にEventSystem.current.SetSelectedGameObject(null)でSetSelectedGameObjectの初期化を行い、再度EventSystem.current.SetSelectedGameObject()で対象パネルでの初期選択ボタンを指定します。
//表示したいUIパネル
public GameObject pousePanel;
public GameObject soundPanel;
//初期選択ボタン
public GameObject pouseFirstbutton;
public GameObject soundFirstbutton;
//ポーズメニューに切り替え
public void SelectedPouseMenu()
{
//初期選択ボタンの初期化
EventSystem.current.SetSelectedGameObject(null);
//初期選択ボタンの再指定
EventSystem.current.SetSelectedGameObject(pouseFirstbutton);
pousePanel.SetActive(true);
soundPanel.SetActive(false);
}
//サウンドメニューに切り替え
public void SelectedSoundMenu()
{
EventSystem.current.SetSelectedGameObject(null);
EventSystem.current.SetSelectedGameObject(soundFirstbutton);
pousePanel.SetActive(false);
soundPanel.SetActive(true);
}
}
サンプル *必要部分のみ抜粋
2枚以上メニューを切り替えたい場合も同じ方法でいけます。

ポップアップ表示の注意
今回のサンプルコードは表示パネル以外非アクティブ化しているため問題になりませんが、ポップアップ表示のような形でメニューを表示すると元のパネル側のボタンを選択出来てしまう場合があります。

これを防ぐためにはButtonのInspecterからButton(Script)の項目でNavigationをAutomaticに変更し、個別に設定する必要があります。

面倒ですが事故を防ぐため…。まあ殆どのパターンではAutomaticで問題無いでしょう。
初期選択ボタン問題の対処は以上です。
スクロールバーの実装
UIの実装作業だと他にスクロールバーの実装がそこそこ時間を喰いました。厄介ポイントなのが初期作成時点で付随するオブジェクトの数が多いこと、項目が多くどれが何を示すのか分かりにくいところでしょうか。
参考にさせて頂いたブログ
それぞれの用語については素直にマニュアル読んだ方が良いです。

カーソルの初期選択に関してはButtonと同じようにInspecterに変数として入れればScriptで制御出来ます。
スクロールバー周りは動画や文章を見ても理解しづらかったので、実際に弄りながら覚えるのが1番早い気がしました。
バグはともだち!こわくないよ!
非エンジニアの身としては出来れば1つも出て欲しくない存在ですが、発生する度に洗いざらい原因を調べるのでとても勉強になります。今回も元をたどれば初歩的なミスでしたし、1つもバグが出ないなんてこと有り得ません。でもやっぱり出て欲しくは無いですね。
五美大展までに追加ステージなどが作れたらなーっと思ってましたが多分無理そうです。itch.ioの方はインコレまでに体験版データ作成頑張ります。