UnityのUIでゲームパッドとキー操作でアイコンを動かしボタン操作を行う

今回はUnityのメニュー画面や持ち物画面等のUIの操作をゲームパッドやキー操作でアイコンを移動しそのアイコンを使って行えるようにしていきたいと思います。

メニュー画面等の操作は一般的にはマウス操作でマウスカーソルを移動させボタンの上に移動させたり、押したりします。

その操作に関しては

Unityでキャラクターの持ち物画面を作成する
Unityのゲームで持ち物画面を作成し、アイテムの情報を見る事が出来るようにします

をご覧ください。

またゲームパッドやキー操作でメニュー画面等のボタンのフォーカスを移動させるやり方は

Unityでキーやゲームパッドで操作するステータス画面の作成
UnityのゲームでPS3コントローラー(ゲームパッド)で操作出来るステータス画面を作成していきます。

UnityのUIのボタンのフォーカスとフォーカス対象の設定
UnityのUIでボタンのフォーカスとフォーカス対象の設定する方法。ボタンをグループに分けて、どちらかのグループのボタンが選択されている時はもうひとつのグループを選択出来ないようにします。

をご覧ください。

スポンサーリンク

今回作成するUIのメニュー操作

今回作成する機能は今までのとどう違うのか?と言うと

ゲームパッドやキーの移動ボタンを押した時に『ボタン等のUIのフォーカスを順番に移動させたり』、『マウスポインタを移動させたり』するのではなく、

移動キーを押した時にアイコンとして作成したゲームオブジェクトを動かし、アイコンがボタン上にある時に決定ボタンを押したらボタンが押されたことにします。

UIメニューの画面の作成と動かすアイコンゲームオブジェクトを作成する

UIメニューの外枠を作成

まずはボタンやアイコンを設置するCanvasを作成します。
Canvasの子要素にはPanelを作成します。

UIメニュー画面の基盤

動かすアイコンの作成

次にゲームパッドやキーで移動キーが押された時に動かすゲームオブジェクトを作成します。

先ほど作成したPanelの子要素にUI→Imageを作成し名前をIconと変更します。

IconのImageコンポーネントのSource Imageに動かしたいアイコン用のスプライトを設定します。

今回はAsset Storeのカテゴリから『テクスチャ&マテリアル』から『アイコン&UI』を選択し値段でソートしたら出てくる『RPG inventory icons』をインポートして
使用させていただきます。

インポートした中からIconのSource Imageにswordを設定します。

Iconのインスペクタ

↑のようにIconのWidthとHeightのサイズを30にします。

IconのタグにはIconというタグを作成し設定しておきます。

アイコンを動かすスクリプトMoveIconの作成

アイコンをゲームパッドやキーで移動できるようにするスクリプトMoveIconを作成し取りつけます。

アイコンは移動キーが押された時に移動させるのでUpdate関数で

移動キー × 移動スピード

でXとY方向の移動値を設定します。

その後、現在の位置に移動値を加えた位置にアイコンを移動させます。

このままだとアイコンが画面外にも移動してしまうので、Mathf.Clampを使ってアイコンのサイズ、画面サイズを使って画面内だけの移動が出来るようにしています。

ここまでを実行して確認してみましょう。

アイコンが画面内のみ移動するサンプル

↑のように画面内のみアイコンのゲームオブジェクトが移動してします。

これでアイコンゲームオブジェクトを移動させる事が出来ました。

アイテム表示ボタンをアイコンで操作

次はアイテム表示用のボタンを作成し、アイコンがボタンの上に来たらアイテム情報をテキストUIに表示するようにしています。

アイテム表示用ボタンの作成

まずはアイテム毎にボタンを作成し、アイテムのImageを表示させます。

Panelの子要素にUI→Buttonを選択し、2つのボタンを作成し名前をAxeとArmorとします。
Buttonの子要素にあるTextは使わないので削除してください。

アイテム用ボタンの階層

↑のようにAxeとArmorボタンが作成されます。

アイテム用ボタンAxeのインスペクタ

AxeとArmorのインスペクタでWidth、Heightを50に設定します。

それぞれのImageのSource Imageには先ほどインポートしたアイコンの中からaxeとarmorを選択し設定します。

またButtonコンポーネントのNavigationをNoneにします。

これは一度何らかのButtonや他のUIが選択状態になった時、他のNavigation項目に設定されていると移動キーが押された時に他のUIへフォーカスが移動してしまう為です。

今回の場合はアイコンを動かしボタンの操作を行う為Navigationによってフォーカスが移動してしまうと困るのでNoneに設定しています。

ButtonのHighlight Colorは赤色に設定し、ボタンの上にアイコンが来たらアイテムボタンのImageを赤くします。

実際のアイテムボタン画像

デフォルトのアイテムボタンは↑のようになりました。

アイテム情報表示用テキストUIの作成

次にPanelの子要素にUI→Textでアイテム情報表示用のテキストを作成します。

ただ情報を表示する為だけのテキストなのでWidthとHeightをお好みの大きさで作成し、配置してください。

アイテム表示用テキストのインスペクタ

今回は↑のように作成しました。

アイコンとアイテムボタンの接触を判定する

次にアイコンとアイテムボタンが接触している事を検知出来なければボタン上にアイコンがあるのかどうかわかりません。

その為、アイコンにはRigidbody2DとBox Collider2D、アイテムボタンにはBox Collider2Dを取りつけます。

今回使用するRigidobodyとColliderは2Dのものを使用します。
これはUIは2Dで表示されるからです。

ちなみに3D用のColliderと2D用のColliderは別のシステムを使って衝突判定を行うので互いに衝突判定や検知は出来ません。

アイコンのRigidbody、Colliderの設定

アイコンゲームオブジェクトのBox Collider2DのIs Triggerにチェックを入れ、コライダのサイズをアイコンのサイズと合わせます。

Rigidbody2DのSleeping ModeをNever Sleepにします。

Rigidbody2DのSleeping Modeはデフォルトの設定では動かしていない時にRigidbodyを無効化しています。

これでは常時接触を確認出来ないのでNever Sleepに設定します。

また連続衝突を検知出来るようにする為、Collision DetectionをContinuousにします。

今回の場合相手方で検知するだけなのでこの設定は意味ないかも?

アイテムボタンのColliderの設定

Axe、Armorのアイテムボタンにはアイコン検知エリアであるBox Collider2Dを設定し、コライダのサイズをボタンのサイズと合わせます。

アイコンを検知する為のスクリプトIconEventスクリプトを作成し取り付けています。

↑がアイコン検知スクリプトです。

コライダは2D用のコライダなので関数名や受け取る引数の型も2Dを付けなくてはいけません。

ここを3D用と同じ関数名にするとイベントが発生しないので何も起こりません。

今回はアイテムボタンの上にアイコンが侵入した時と上にいる間CheckEvent関数を呼び出します。

CheckEvent関数では接触したゲームオブジェクトのタグがIconタグだった時でEventSystemがどのUIもフォーカスしていない時にこのゲームオブジェクト(アイテムボタン)を
フォーカスします。

インスペクタで設定したitemNameの名前に応じてテキストUIにアイテムの情報を表示しています。

今回はサンプルなので文字列をその場で入れていますが、アイテム情報クラス等を作ってそこでアイテムに関する情報を入れておき、そこから情報を取り出すように
した方がいいと思います。

またSubmitに設定されているボタンを押した時にMoveIconスクリプトのSetMoveItem関数を呼び出し、このアイテムのSpriteを渡します。

ボタンの入力設定については

UnityでPS3コントローラー(ゲームパッド)に対応して動かしてみる
UnityのゲームでPS3コントローラー等のゲームパッドを使用してみます。パソコンのゲーム用コントローラーを持っていない人は便利かもしれません

を参照してください。

InputManagerのSubmit設定

↑のようにInputManagerで新しくSubmitを作り、ゲームパッドの決定ボタン(わたくしの場合PS3コントローラの○ボタン)を設定します。

アイテムを装備する機能を作成する時にアイテムを選択し装備スロットに移動させます。

その時アイコンと一緒にそのアイテムを表示させ、
装備スロットの上でSubmitボタンを押した時にそのスロットにそのアイテムを表示させるようにします。

この時に装備するアイテムのSprite情報が必要な為SetMoveItem関数で設定しています。

Submitボタンが押された時はInput.GetButtonDownで取得する事が出来ますが、GetButtonDownはそのフレームで1回しか処理されないので、

マウスアイコンがアイコン上にきてすぐにSubmitボタンを押しても反応しない事があります。

その為Input.GetButtonを使って次のフレームに移動しても押している事を検知するようにしています。

SetMoveItem関数の記述は後で行います。

OnTriggerExit2D関数ではアイコンがアイテムボタン上から離れた時にフォーカスを外し、アイテム情報を表示するテキストUIを元の文字列に変更しています。

Iconの左上に選択したアイテムを表示する

さきほどアイテムボタンの上でSubmitボタンを押したらそのアイテムをアイコンと一緒に移動させると言いましたが、

今回はあらかじめアイコンの左上にImageを作成しておき、アイテムが選択された時にアイテムのImageの設定と表示を行うようにします。

Iconの子要素にUI→Imageを選択し作成します。

Iconの子要素にImageを作成

↑のようにアイコンの左上に移動し、アイコンのサイズより少し小さくします。
またImageコンポーネントのチェックを外し、Source ImageはNoneにしておきます。

Iconの左上に小さいImageがある

↑はImageコンポーネントを有効化して一時的に表示した画像です。
Iconより少し小さいサイズで左上に配置しているのがわかると思います。

MoveItemスクリプトの修正

MoveItemスクリプトにアイテムボタンを押した時にアイテムのSpriteを設定する処理等を追加しましょう。

↑のようにアイテムボタンを押した時(アイテムボタン上でSubmitボタンを押した時)は受け取ったSpriteを左上のImageスプライトに設定し、Imageを表示しています(SetMoveItem)。

moveItemにはインスペクタでIconの子要素であるImageを設定しておきます。

GetMoveItemはアイテムのImageを返し、ResetMoveItemは装備スロットにアイテムを移動した時にIconの左上のImageを非表示にしImageスプライトをnullに設定しています。

装備スロットの作成

アイコンでボタンアイテムを押した後、装備スロットの上でSubmitボタンを押した時に装備スロットにアイテムのSpriteを表示出来るようにします。

まずは装備スロットを作成していきましょう。

簡易装備スロットのヒエラルキー

↑のようにPanelの子要素にUI→Buttonを作成し名前をDropDownSlotとします。

その子要素にUI→Imageを作成します。

子要素のImageのSource Imageをアイテムのスプライトにし、ボタンのスプライトは白い背景のまま残します。

装備スロットボタン

↑がDropDownSlotボタンのインスペクタです。
Width、Heightを50、NavigationをNoneにしておきます。

装備スロット用Image

↑が子要素のImageです。

DropDownSlotのサイズより少し小さくしWidth、Heightを40とします。

Source ImageはNoneにします。

DropDownSlot範囲内でのイベントを処理するDropDownItemスクリプトの作成

DropDownSlotにはアイコンがボタン上にきてSubmitボタンを押した時に処理をするスクリプトDropDownItemスクリプトを作成し取りつけます。

処理は今まで見てきたスクリプトとほとんど変わりません。

Iconにアイテムが設定されている時はDrowDownSlotの子要素のImageに同じSpriteを設定し、Iconで設定していたアイテムを解除しています。

これで機能が完成しました。

Unityを実行して確認する

それではUnityの実行ボタンを押して機能を確認してみましょう。

メニュー画面の操作サンプル

↑のようにアイテムを選択するとアイコンの左上にそのアイテムが表示され、それを装備スロットの上に持っていきSubmitボタンを押すと
アイコンの左上のアイテムが消え、装備スロットにアイテムが表示されました。

↑のサンプルはマウスアイコンがアイコン上にある時の処理でInput.GetButtonDownを使用して判断しているので、ボタンを押してもマウスアイコン左上のアイコンが変わらない事があります。

この記事ではInput.GetButtonDownをコメント化しInput.GetButtonを使用しているのでこの問題は出ないようになっています。

終わりに

今回の機能を作成したのは、家庭用据え置きゲームでコントローラーを使ったUIの操作に似たものを作成したかったからです。

単純にUIの要素のフォーカス移動でアイテムを選択するものが多いですが、ユーザーがUI内で自由に操作アイコンを移動出来る機能もほしかったからです。

んー・・でもフォーカスを単純に移動する方がステータス画面の操作としては簡単かも!?(^_^;)

スポンサーリンク

記事をシェアして頂ける方はこちら

フォローして頂くとやる気が出ます