Unityでキーやゲームパッドで操作するステータス画面の作成

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

マウスを使ったステータス画面は

Unityでキャラクターの持ち物画面を作成する
Unityのゲームで持ち物画面を作成し、アイテムの情報を見る事が出来るようにします
持ち物画面で装備スロットに装備品を入れる機能をUnityで作る
Unityの持ち物画面で装備スロットにマウスのドラッグ&ドロップで武器を設定出来るようにします
Unityで現在装備している武器のスロットがわかるようにする
Unityのゲーム中の画面に装備スロットを表示し、現在装備している武器もわかるようにします

で作成しましたが、キーボードやゲームパッドに対応していませんでしたので、
これらの機能をキーとゲームパッドでの操作でボタンの選択が出来る別のステータス画面を作成したいと思います。

スポンサーリンク

ステータス画面UIを作成していく

まずはステータスメイン画面を作成していきます。

ヒエラルキー上で右クリック→UI→Canvasを選択し、名前をPropertyにします。
Propertyの子要素にUI→Panelでパネルを作成し、名前をBackgroundにします。

BackgroundのRectTransform左のAnchorで縦横をStretchにします。
Backgroundの子要素にUI→Panelでパネルを作成し、名前をMainWindowにします。

MainWindowのRectTransform左のAnchorで縦横をStretchにします。
これでBackground、MainWindowはPropertyの大きさで変動します。

ステータス画面(キー操作)1

MainWindowの子要素にUI→Panelで3つのパネルを作成し、名前をTitle、MenuArea、Informationとします。
TitleとInformationの子要素にUI→Textでテキストを作成し、タイトルと説明文の初期テキストを設定しておきます。

MenuAreaの子要素にUI→Buttonで3つのボタンを作成し、名前をEquip、Item、Exitとします。
子要素にはTextが自動で作成されるので

Equipには装備
Itemにはアイテム
Exitにはゲームに戻る

という初期テキストを設定します。

ステータス画面(キー操作)3

上の画像のように領域を作成します。
上の画像で確認出来ますが、パネルの領域の4隅に矢印のようなものが出るのでそれをドラッグして領域を変更します。

ステータス画面(キー操作)4

MenuAreaのインスペクタにAdd CompoenntからLayout→Horizontal Layout Groupを追加します。

Horizontal Layout Groupは設定したMenuAreaの子要素を横に整列させる為に設定しています。
今回の場合はEquip、Item、Exitボタンを横に整列させる為に設定しました。

設定項目のPaddingは親要素からの距離を指定し、Spacingは他要素との距離になります。

値を変えて好みの設定値を探ってください。

これでステータスメイン画面が出来ました。

Exitボタン等のイベント処理をするButtonEventスクリプトの作成

次にExitボタンを押した時の処理を作成していきます。
(Equip、Itemの処理は装備画面、アイテム画面を作成していないので後で作成します)

Exitボタンを押した時はゲームの画面に戻らなければなりません。
その為の処理を行うButtonEventスクリプトを新しく作成し設定します。

Selected関数はキー操作で選択された時に実行する自作関数です。

UI.Buttonの状態遷移が有効である時はEventSystems.EventSystem.currentで現在使用しているイベントシステムを取得し、currentSelectedGameObjectで現在選択中のゲームオブジェクトを調べます。

自分自身のゲームオブジェクトが選択されていない場合はSetSelectedGameObjectで自身のボタンを選択状態にします。

DisableWindow関数はExitボタンを押した時に実行する自作関数です。

WindowOnOffはEquip、Itemボタンを押した時に使用する関数でExitボタンでは使いません。(Equip、Item、Exitには共通でButton Eventスクリプトを使用します)

関数毎にGetComponentでUI.Buttonを取得していますが、これはStart関数内で取得し変数に入れて利用した方がいいですね・・・(^_^;)
毎回取得してると処理が遅くなるかもしれません。

MainWindowのExitボタンを押した時に実行する関数をEvent Triggerで設定する

次にExitボタンが押された時にさきほど作成した関数を呼び出すようにします。
その為にExitボタンのインスペクタでAdd Component→Event→Event Triggerを選択し追加します。

イベントに関しては

UnityのUIのクリックやドラッグのイベントを受け取る
UnityのUIのクリックやドラッグのイベントをEvent Triggerコンポーネントを取りつけて受け取れるようにします

を参照してください。

Event TriggerコンポーネントのAdd New Event Typeをクリックしイベントが発生した時に呼び出す関数を指定します。

呼び出す関数が指定されているゲームオブジェクト(今回の場合Exitゲームオブジェクト)を指定した後、関数を指定します。

ステータス画面(キー操作)5

Selectはキー操作でボタンを選択した時のイベントでゲームオブジェクトにExitボタン、関数はSelectedを指定。

Pointer Enterはマウスがボタン上に入った時のイベントでゲームオブジェクトにExit、関数はSelectedを指定。

Pointer Downはマウスをボタン上で押した時のイベントでゲームオブジェクトにExit、関数はDisableWindowを指定。

Submitはキー操作でEventSystemのSubmit Buttonに指定されているキーが押された時のイベントで、ゲームオブジェクトにExit、関数はDisableWindowを指定。

Pointer Exitはマウス操作でボタン外に移動した時のイベントでゲームオブジェクトにExit、関数はButtonのOnDeselectを指定。

マウスでボタン外に出たらボタンを選択している状態から解除させます。

Button EventスクリプトのインスペクタにInformationテキストと表示するテキストの内容を設定します。

このようにEvent Triggerでイベントが発生した時に実行する関数を指定する事でボタンに対する操作をする事が出来ます。

これでExitボタンの処理が完成しました。

ステータス画面を開くStopGameを作成

ステータス画面は最初は表示しない状態にしておくので、何らかのボタンを押したらステータス画面を表示するというスクリプトが必要になります。

そこで、ステータス画面を開くスクリプトStopGameを全体を管理するスクリプトに記述します。
全体を管理するスクリプトはゲーム内に常にあるゲームオブジェクトに取りつけてゲーム全体を管理する内容を記述します。

キー操作でStartボタンに設定されたキーを押した時にインスペクタで設定したPropertyをOn・Offします。
Start等の独自のボタン設定はUnityのメニューのEdit→Project Settings→Inputで作成出来ます。

最初にひとつだけゲームオブジェクトを選択状態にしておかなければならない

ステータス画面を開いたり・閉じたりするスクリプトが出来たので、ステータス画面のOn・Offの確認をする為、実行してみましょう。

マウス操作では問題はないですが、キー操作で問題が発生します。

キー操作をする場合はあらかじめ何らかのゲームオブジェクトが選択されていないと他のボタンをフォーカスする事が出来ないので、
あらかじめ最初に設定するボタンをフォーカスしておきます。

今回はキー操作をする事をメインに考えているので、ステータスメイン画面が開かれたら何らかのゲームオブジェクトを選択状態にしておきます。

ゲームオブジェクトを選択状態にするには、EventSystemのSetSelectedGameObject関数を使用します。

EventSystemのインスペクタのFirst Selectedで最初に選択するゲームオブジェクトを指定出来ますが、
今回のステータス画面のように何度も開いたり閉じたりする場合は最初の1回しか作用しないので、こちらは使いません。

ステータスメイン画面がアクティブになった時にEventSystemのSetSelectedGameObjectを使って選択状態にします。
それでは選択状態にするスクリプトSelectScriptを作成します。

OnEnable関数はスクリプトを指定したゲームオブジェクトがアクティブになった時に呼ばれるイベント関数です。
最初にnullを指定し選択を解除した後に選択したいゲームオブジェクトを指定します。

ステータスメイン画面が開かれた時にEquipボタンを選択状態にする事にします。

EventSystemの選択しているゲームオブジェクトがハイライト表示されない

ここで少し不具合が発生します。

EquipボタンにこのSelectScriptを指定するとEventSystemでは選択状態になっているはずなのに、ボタンがハイライト表示されません。

ボタン自体はイベントシステムに選択はされているのでEquipの所にキーの選択状態はあります。
が、ボタンの状態が選択されていない時(Disable)と同じ色になっているのでわかりません。

キー操作をしてみるとわかりますが、→や←のキーを押すとEquipが選択されていたのがわかります。

動作に問題はないですが、最初に選択状態にしたゲームオブジェクトがどれなのかわからない状態で始まります。
正直な所、何が原因でこの現象になっているのかわかりませんが・・・・(^_^;)

もしかするとスクリプトの順序の影響なのかも?

SelectScriptを見て頂ければわかる通り、最初に選択するゲームオブジェクトは

transform.parent.gameObject

と、スクリプトが設定されているゲームオブジェクトの親のゲームオブジェクトを指定しています。

対処法としてはEquipの子要素であるTextにSelectScriptを設定してください。

選択したいEquipの子要素がアクティブになったタイミングだとうまくいくようです。
この処理に結構悩まされました・・・・・(=_=)。

アイテム画面のUIを作成していく

次はアイテム画面を作成していきます。

ステータス画面(キー操作)6

Backgroundの子要素にUI→Panelでパネルを作成し、名前をItemWindowにします。

ステータス画面(キー操作)8

MainWindowとほとんど同じ項目を作成していきます。
ItemAreaTitleとItemAreaはPanelです。

Informationの子要素であるTextにInformationTextという新しいタグを作成し設定しておきます。

これでアイテム画面が出来ました。

MainWindowのItemボタンを押した時に呼び出す処理をEvent Triggerで設定する

MainWindowのItemボタンを押した時にアイテム画面を開くように設定します。

ステータス画面(キー操作)9

MainWindowのItemボタンにEvent Triggerコンポーネントを追加し、Exitボタンに設定した時と同じように設定します。

SubmitとPointer DownにはButton EventのWindowOnOff関数を指定し、渡す引数にItemWindowを指定します。
Submitはキー操作のEnterやSpaceキーの決定キーを押した時、Pointer Downはマウスの左ボタンを押した時にイベントが発生します。

Cancelの時には新しく作るReturnGameスクリプトのReturnGame関数を呼び出します。(これは後で作成するので作成した後で設定してください)。
CancelはCancelのキーが押された時に発生するイベントです。デフォルトではEscキーが対応しています。

WindowOnOff関数内でPropertyゲームオブジェクトに設定しているWindowOnOffスクリプトのChangeWindowを指定しています。
(WindowOnOffスクリプトはこのあと作成していきます)。

ButtonEventスクリプトのWindowOnOff関数とWindowOnOffスクリプトと同じ名前を使っているのでわかりづらいですね・・・(^_^;)

Propertyゲームオブジェクトにステータス、装備、アイテムの切り替えをするWindowOnOffスクリプトを追加

Propertyゲームオブジェクトに新しくWindowOnOffスクリプトを作成し、設定します。

ChangeWindow関数では受け取ったウインドウゲームオブジェクトをOnにし、他のウインドウをOffにします。

ステータス画面(キー操作)10

Propertyゲームオブジェクトに設定したWindowOnOffスクリプトのインスペクタで上のように設定します。

これでItemボタンを押した時にアイテム画面が開くようになりました。

Exit以外のボタンが選択状態にある時Cancelボタンを押したらExitに戻るReturnGameの作成

Event TriggerのCancel時に呼び出すスクリプトReturnGameを作成していなかったので、作成していきます。

インスペクタで指定されたボタンを選択状態にするだけです。
インスペクタではExitボタンを設定しておきます。

このReturnGameスクリプトは何をしているかというと、EquipやItemボタンが選択状態にある時にCancelボタンを押したら、Exitボタンを選択させる為です。

例えばCancelボタンにPS3コントローラの×ボタンが設定されていて、今Equipボタンが選択状態の時に
×ボタンを1回押せばExitボタンが選択状態になり、もう1回押せばゲームに戻るというように、キャンセルボタンを押した時に画面を簡単に遷移させる為の処理です。

と、言いつつExitボタンではCancelボタンの処理をしていないのでExitボタンにもCancelボタンを押した時にゲームに戻るような処理を追加しなければいけません(今回は作りません)。

これでステータスメイン画面→アイテム画面の遷移が出来ました。

ItemWindowのExitボタンにもイベントトリガーを追加し、アイテム画面→ステータスメイン画面へと遷移するように設定してください。

設定は画面の指定以外は同じです。
これでアイテム画面の外枠は出来上がりました。

アイテム画面にアイテムを表示していく機能を作成

次にアイテム画面が表示された時にアイテムを表示していく処理が必要になります。

アイテムはItemAreaの子要素に追加していきます。
ItemAreaのインスペクタでAdd ComponentでLayout→Grid Layout Groupを追加します。

ステータス画面(キー操作)11

Cell SizeのX、Yを50、SpacingをX、Yを5に設定します。

ItemAreaにレイアウトを設定したので、ItemAreaの子要素に要素を追加するとこのレイアウト設定に従って並びます。
ItemAreaの子要素に追加するアイテムボタンのプレハブを作成する前に、アイテムに関するスクリプトを作成していきます。

アイテムデータを表すItemDataスクリプトの作成

まずはアイテムクラスを作成します。
JavaScriptでItemDataスクリプトを作成します。

通常のJavaScriptでクラスを作成する時は別のやり方ですが、UnityのJavaScriptだとこういう風に作るみたいです。

スクリプトファイル名と同じクラス名で宣言し、メソッドの部分に関数と同じやり方で処理を書いていきます。
クラス名と同じ関数を作成するとコンストラクタになります。

このItemDataはアイテムの情報を保持するだけのクラスです。

アイテム情報を管理するItemDataBaseスクリプトの作成

次にゲーム内で使用するアイテムのデータを管理するItemDataBaseスクリプトを作成します。

ItemDataBaseでは先ほど作成したItemDataクラスを使ってアイテム情報を登録していきます。

Resources.Load(“sword”, Sprite)

Resources.Loadを使うとAssetsエリアに作成したResourcesフォルダの第1引数で指定した名前の物をロード出来ます。

アイテムを表すアイコンのSpriteはResourcesフォルダを作成しその中に入れておきます。
(今回使用するアイコンはAsset Storeのテクスチャ&マテリアルのカテゴリのRPG inventory iconsを使用させて頂いてます)

Resourcesと名前を付けたフォルダは特殊フォルダになりますので、他の名前には出来ません。
Resourcesフォルダに入れたゲームオブジェクトはインスタンス化しなくてもResources.Loadで読み出せます。

これでアイテムクラスとアイテムデータベースの作成が終わりました。

主人公のステータスを保持するMyStatusスクリプトの作成

次は主人公がアイテムを持っているかどうかもわからなければならないので、主人公にステータススクリプトを設定します。
新しくMyStatusというスクリプトを作り主人公に設定してください。

MyStatusではテスト用にアイテムをいくつか所持状態にし、装備スロットに装備を設定しておきます。

列挙型のenumでなぜ一つだけYumiとローマ字になっているんでしょうか・・・・(^_^;)
まぁ・・・いいか。

これでアイテムクラス、アイテムデータベース、キャラクターのステータスのスクリプトが完成しましたので、次はアイテム1つ1つを表現するプレハブを作成していきます。

アイテム一つ一つを表すItemButtonプレハブを作成する

アイテム1つは1つのパネルとボタンで表し、ボタンのアイコンに2Dのスプライトを表示するようにします。

UI→Panelを選択しパネルを作成したらItemButtonという名前にします。
ItemButtonの子要素にUI→Buttonを選択しボタンを作成したらItemButtonという名前にします。

ItemButtonプレハブ

↑のような階層になります。

ステータス画面(キー操作)14

ItemButtonのインスペクタでButtonコンポーネントのHighlighted ColorとPressed Colorの色を一緒にしてください。

これはアイテムの情報を見るだけなので、ボタンが押されてもやる事がない為、同じ色に設定して押しても何も起きていないように見せたい為です。(実際に押してもイベントを受け取っていないので何も処理をしてません)

ItemButtonのイベント処理を行うItemButtonスクリプトの作成

子要素のItemButtonにAdd Componentから新しいスクリプトItemButtonを作り設定します。

このボタンが選択された時にSelected関数を実行し、このボタンに設定されているアイテム情報をアイテムデータベースから取得し、InformationのTextに表示します。

itemNum変数はこのボタンに設定しているアイテム情報を得る時に使用するボタン毎に設定する番号で、この番号を使ってアイテムデータベースから情報を取得します。
itemNumはボタン毎に設定されますが、ボタン番号がアイテムデータベースでのアイテム番号と一致するようになっています。

ItemButtonのイベントが発生した時に実行する関数を設定する

ステータス画面(キー操作)12

子要素のItemButtonにAdd Component→Event→Event Triggerを追加し、イベントトリガーを設定します。
上の画像のように設定します。

ボタンのイベントが発生したら実行する関数を指定しています。

これでアイテムの1つ1つの入れ物が完成しました。

ItemAreaにアイテムの総数分ItemButtonを表示するSetItemButtonスクリプトの作成

アイテム画面が表示される時に、ItemButtonをアイテムデータベース分だけ作成し、ItemAreaの子要素に表示するようにします。

ItemAreaに新しいスクリプトSetItemButtonを作成し、設定します。

itemButton変数はpublicで宣言しているので、インスペクタでさきほど作成したItemButtonプレハブを設定します。

OnEnable関数はこのスクリプトが設定されているItemAreaがアクティブになった時に自動で実行されます。

アイテムデータベースに登録されているアイテムの数分だけItemButtonインスタンスを作成し、親要素をItemAreaに設定します。

ItemAreaにはGridLayoutが設定されているので、子要素であるItemButtonはそれに従って並んでいきます。

主人公のステータスを確認し、そのアイテムを持っている場合は子要素のItemButtonのImageにアイテムのアイコンを設定します。

そのアイテムを持っていない時はImageコンポーネントを使用不可にし、ボタンの状態変更を無効化しておきます。

最後にアイテムボタン毎にユニークな番号を設定します。
このユニークな番号とアイテムデータベースの登録番号は一致します。

OnDisable関数はItemAreaが非アクティブになった時に自動で呼ばれます。
作成したアイテムボタンインスタンスを全部削除します。

ステータスメイン画面からアイテム画面を開いて確認する

これでアイテム画面が完成したので、ステータスメイン画面からアイテム画面を表示してアイテムが表示されるか確認してみます。

ステータス画面(キー操作)13

MyStatusでは

とアーマーの所持部分はコメント化しているのでアイテム一覧のアーマーの部分はアイコンが表示されず、キー操作やマウス操作にも反応しません。

アイテムの上にキー操作やマウス操作で選択状態を移動するとInformationのText部分にアイテムの情報が表示されます。

これでアイテム画面の動作確認は終了です。

うん、なかなかよく出来てる・・・(^_^)v

装備画面のUIを作成していく

ここまででずいぶん長くなりましたが、実はここからが一番面倒くさい処理です。(+_+)

装備スロットに武器を設定する装備画面の作成をしていきます。

では装備画面を作成していきましょう。

ステータス画面(キー操作)15

アイテム画面を作成する時と同じように装備画面を作ります。

EquipAreaにはAdd Component→Layout→Grid Layout Groupを追加します。
設定する値はアイテム画面のItemAreaに設定したのとほとんど同じ値です。

設定する値は後で画像で紹介します。

ステータス画面(キー操作)17

装備画面の作成は色々面倒くさい・・・

マウス操作でドラッグ&ドロップする処理も色々面倒な処理をしなければいけませんでしたが、残念なことにキー操作やマウスで押して装備を変更するのもなかなか面倒な処理が絡んできます。

面倒な処理というのは装備スロットの一つをキー操作のSubmitやマウスを押した時に装備できる武器のアイテムボタンだけを選択出来るようにして、それが終わったらまた装備スロットやメニューボタンの選択が出来るようにしなければいけません。

つまり、装備スロットの選択と装備するアイテムの選択でキー操作で移動出来る項目に制限を設ける必要が出てくるんです。

キー操作する場合はこれが面倒ですね・・・・(^_^;)

ではEquipAreaのインスペクタに設定するコンポーネントを見ていきます。

ステータス画面(キー操作)18

Grid Layout Groupの設定項目でConstraint Countを3、他はアイテム画面でItemAreaに設定したLayoutの値と同じにします。

SetEquipButtonスクリプトは装備スロットをEquipAreaに表示するスクリプト
SelectedEquipButtonは装備スロットのボタンが押された時にどのボタンが押されたかを記憶しておくスクリプト
InteractiveButtonは設定したゲームオブジェクト(ここではEquipArea)の子要素のボタンを無効化するスクリプト

になります。

装備しているアイテムを表示するEquipButtonの作成

スクリプトを作成する前にSetEquipButtonでEquipAreaに設置する装備スロットボタンを作成します。

アイテム画面で作成したItemButtonと同じようにUI→Panelでパネルを作成し、名前をEquipButtonとします。
EquipButtonの子要素にUI→Buttonでボタンを作成し、名前をEquipButtonとします。

EquipButtonのインスペクタにAdd Componentから新しく作ったスクリプトEquipButtonとMyButtonを追加します。

EquipButtonのイベントを処理するスクリプトEquipButtonの作成

EquipButtonスクリプトはEquipButtonボタンのイベントを処理するスクリプトです。
もう名前で混乱するわ!(`A´)

itemNumはレイアウト上作成するボタンを含めた番号でmyNumberは装備スロットの番号で4までになります。
(変数名が分かりづらいので変数名は最適なものに変換してください)

FocusEquipItem関数はEquipButtonが押された時に実行される関数でSelectedEquipButtonスクリプトに押されたレイアウト上の番号と装備スロットの番号を保存し、EquipAreaの子要素のボタン、メニューエリアのボタンを無効化します。

その後にEquipItemArea(武器のアイテムが並ぶエリア)のボタンを有効化します。

UI.Buttonのまま使うとうまくいかないので、UI.Buttonを拡張してMyButtonスクリプトを作成する

次にMyButtonスクリプトを見ていきます。

public class スクリプト名 exnteds 継承元クラス{
}

上のようにextendsを使うと継承出来ます。
継承を使うと継承元の機能はそのままに継承した方で機能を上書きしたり追加したり出来ます。

UI.Buttonを継承してMyButtonを作成しています。

UI.Buttonのinteractableでボタンの状態を無効化し、Disabledに遷移させようとしましたが
なぜかSubmitしたボタンがノーマル状態のままになってしまいました。

ボタンを押された時にDostateTransitionでDisabledに状態を遷移させようとしましたが、DostateTransitionのアクセス制限がprotectedでアクセス出来なかった為継承してDostateTransitionを上書きし、無理やりやってみようと思いました。

が、コメント化している通り何もしなくてもちゃんと動作したので処理は何もしていません。

んーなにが違うんでしょう・・・・(^_^;)

UI.Buttonのまま使用出来ればわざわざ拡張したMyButtonを作成する必要はありませんのでご自分の環境に合わせてください。

EquipAreaにEquipButtonプレハブを設置するSetEquipButtonスクリプトの作成

次にEquipButtonプレハブをEquipAreaに表示するスクリプトSetEquipButtonを作成します。

装備スロットにアイテムがセットされていなければspriteにnullを設定しておきます。

レイアウトの為だけに作成するスロットはフォーカスさせない為にボタンのinteractrableをfalseにしています。

どのEquipButtonが押されたか保持しておくSeectedEquipButtonの作成

EquipButtonの作成が終わったので、EquipAreaに設定したSelectedEquipButtonスクリプトを見ていきます。

SelectedEquipButtonスクリプトは押されたEquipButtonがどれなのか?を保存しておく為だけのスクリプトです。

エリアのボタンを有効化するInteractiveButtonスクリプトの作成

次にInteractiveButtonスクリプトを見ていきます。

OnInteractable関数はゲームオブジェクトの子要素を探索し、ボタンを有効化させる関数です。

ゲームオブジェクトの名前がEquipItemButton、EquipButton、Item、Exitという名前だった時、それをボタンと認識し、ボタンの有効化をしています。

focusGameObjectに最初に有効化したボタンを入れて、ループの最後にEventSystemのSetSelectedGameObjectで指定し、そのボタンを選択状態にします。

ボタンではなかった時はその子要素も検査する為、再帰呼び出しで細部まで調べます。

EquipButtonだった時はレイアウト上の使わないボタンまで有効化されては困るので、装備スロットの表示位置のボタンだけ有効化します。

Item、Exitの時はUI.Button、EquipItemButtonとEquipButtonの時はMyButtonコンポーネントを取得しています。

この違いはボタンの状態の遷移のOn・Offをするinteractableの作用が利かない事があるのでその対処の為です。
MyButtonはさきほどUI.Buttonを拡張したクラスとして作成したものです。

InteractiveButtonスクリプトはEquipWindowのMenuArea、EquipItemAreaにも設定してください。

装備用アイテムを選択している間はEquipAreaのボタンだけではなくMenuAreaのボタンも無効化する為です。
またEquipItemAreaのボタンが押されたらEquipItemAreaのボタンを無効化するのでその時にも使います。

これでEquipAreaの処理が出来ました。

EquipButtonのイベントが発生した時に実行する関数を設定する

EquipButtonの子要素のEquipButtonにAdd Component→Event→Event Triggerを設定し

ステータス画面(キー操作)19

上のようにイベントを設定します。
あ・・・Pointer Exit使ってないのに入ってる・・・・((+_+))

装備するアイテムを表示するEquipItemAreaに表示するEquipItemButtonの作成

次は装備スロットを選択した時にその装備スロットに装備するアイテムを選ぶエリア
EquipItemAreaのアイテムボタンの作成をしていきます。

ボタンはEquipButtonの時と同じように作り名前をEquipItemButtonとします。

ステータス画面(キー操作)20

EquipItemButtonに新しくEquipItemButtonスクリプトを作り追加します。
またMyButtonも追加し、NavigationをExplicitにします。

今までのボタンはNavigationをAutomaticにして自動でキー操作の行く先を指定していましたが、
Explicitにすると自分でキー操作をした時の移動先を指定出来ます。

EquipItemButtonのイベントが発生した時に処理するEquipItemButtonスクリプトの作成

インスペクタでゲームオブジェクトを設定する事も出来ますが、今回の場合スクリプトでボタンを作成し、
かつ移動出来るボタンの制限も加えるので、Explicitの値もスクリプトから設定します。

Update関数内でボタンのinteractableがtrueの時にこのボタンの上下左右からキー操作で移動出来る場所を探します。

upButton = GetComponent.<MyButton>().FindSelectable(Vector3.up);
downButton = GetComponent.<MyButton>().FindSelectable(Vector3.down);
leftButton = GetComponent.<MyButton>().FindSelectable(Vector3.left);
rightButton = GetComponent.<MyButton>().FindSelectable(Vector3.right);

FindSelectableの引数に探す先をVector3で指定します。右側を探すならVector3(1, 0, 0)という具合になります。
すべてVector3のプロパティで指定しています。

見つからなかったらnullが返ってくるのでnullじゃない時かつ見つかったゲームオブジェクトがEquipItemAreaのボタンである時はNavigationのSelectOnUp(上方向の移動先)等に設定をします。

これでボタン自身が移動先を探します。
EquipItemButtonという名前のゲームオブジェクトに限定しているので、他のエリアのボタンにはキー操作では到達しません。

Decide関数はボタンをSubmitした時に実行する関数で、選択したアイテムを選択中の装備スロットに入れるのと、EventSystemの選択するゲームオブジェクトを先ほど選択した装備スロットに戻します。

EquipItemAreaのボタンを無効化し、MenuArea、EquipAreaのボタンを有効化します。

ステータス画面(キー操作)21

EquipItemButtonに設定するスクリプトが完成したので、上のようにEquipItemButtonにEvent Triggerを追加しイベントを設定します。

EquipItemAreaにEquipItemButtonを表示するSetEquipItemButtonの作成

EquipItemButtonが完成したので、EquipItemAreaにEquipItemButtonを設置するスクリプトを作成していきます。

EquipItemAreaに新しくSetEquipItemButtonというスクリプトを作成し追加します。

EquipItemAreaには所持していて装備出来るアイテムだけを表示します。
その為にfor文の中で条件を指定してEquipItemButtonを表示します。

今回は武器アイテムにItem.Weaponというアイテムの種類を入れているのでその一覧を表示します。
防具や盾等も入れる場合はアイテムの種類を増やし、アイテムを作成する時に種類を指定します。
またこのスクリプト内の条件に防具や盾を加えます。

やっている事は今まで出てきたスクリプトと同じです。

ステータス画面が出来たので確認してみる

これでステータス画面が完成しましたので、確認してみてください。

ステータス画面(キー操作)22

上の画像が装備スロットを選択している時の状態です。
上のスロットを選択している状態なので剣が赤くなっています。

ステータス画面(キー操作)23

上の画像が装備スロットを選択した後の画像です。
装備アイテム選択エリアに操作が移動し、装備アイテム選択エリア外のボタンは無効化され移動出来なくなります。

最後に動画で紹介します。

ステータス画面の確認サンプル動画

↑のようになります。

実は装備スロットの操作を間違えていました・・・・(^_^;)
あらかじめ装備スロットに武器を置いておかないと選択できない状態になっているので、何もないスロットに新しく武器を設定出来ません。

EquipButtonスクリプトのSelected関数内、SetEquipButtonスクリプトのOnEnable関数内の処理を変更し対応しました。
それぞれのスクリプトの記述は修正してあります。

ふぅ・・・・ようやくステータス画面が完成しました。

ゲーム中に装備スロットを表示する機能の作成

最後にゲーム中に装備スロットを表示し4つの装備スロットから装備を変更する機能を作って終わりになります。
ゲーム中に武器を変更するので装備スロットは武器専用のスロットである必要があります。

ゲーム中の装備スロットUIを作成する

まずはゲーム中に表示する装備スロットを作成していきます。

ステータス画面(キー操作)24

UI→Canvasでキャンバスを作成し、名前をEquipSlotとします。
子要素にUI→Panelでパネルを作成し、名前をEquipSlotAreaとします。

EquipSlotAreaの子要素にUI→Buttonでボタンを4つ作成し、名前をSlot1~4と付け、子要素のTextをすべて削除します。

ステータス画面(キー操作)25

上が配置した画像です。

ゲームスタート時は装備スロットを表示したくないので、EquipSlotAreaはインスペクタで非アクティブにしておきます。

EquipSlotAreaの表示・非表示をするEquipSlotOnOffスクリプトを作成する

EquipSlotAreaはゲームパッドの十字キーとマウスの右クリックを押した時に表示するようにします。
その為の機能をEquipSlotOnOffという名前でスクリプトを作りEquipSlotに設定します。

showTimeが一度表示されてから非表示にするまでの時間で、elapsedTimeが表示されてからの時間です。

UnityのメニューからEdit→ProjectSettings→Inputで十字キーに対応するボタンの設定を行ってください。

キーパッドの対応は

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

を参考にしてください。

キーが押されたら自身の子要素であるEquipSlotAreaを表示します。
表示時間が表示させている時間を超えた時に非表示にします。

ステータス画面操作をする時はTime.timeScaleを0にしてゲームを中断させるようにします。
ステータス画面操作中はキーを受け付けないようにします。
なのでTime.timeScaleが0より大きい時の条件を入れています。

が・・・、後でステータス画面を開いた時は強制で装備スロットを消すようにしたのでこの条件はいらないかも・・・。

ステータス画面を開いた時は中断するようにする

ではステータス画面を開いた時にTime.timeScaleを0に変更する処理と、閉じた時に1に戻す処理を加えます。

全体を管理するスクリプトに設定したStopGameは

となります。

またステータス画面のExitボタンを押した時にTime.timeScaleを1に戻す必要があるので、
ButtonEventスクリプトのDisableWindow関数は

となります。

ゲームの中断機能に関しては

Unityでゲームの中断が出来るようにする
Unityのゲームで一時中断してポーズの表示をする機能を作成していきます。

を参考にしてください。

Slotボタンがキー操作で選択された時に色と装備を変更するSelectEquipスクリプトの作成

次にEquipSlotAreaに新しいスクリプトSelectEquipを作成し設定します。
このスクリプトは装備スロットにアイコンを表示し、押されたキーに応じてアイコンの色を変更します。

Start関数内で装備スロットと対応するアイテムのアイコンを取得します。

Update関数では押されたキーパッドに対応したボタンの色を赤に変更します。
押されたボタン以外は白色にします。

本来であればここで選択された装備スロットに対応する武器をMyStatusに登録する所なんですが、武器のゲームオブジェクトと装備スロットに設定している武器アイテムとの対応付けの機能を作っていないので、コメント化しています。

ResetButton関数はスロットボタンが押された時に一旦全部を白色に初期化する処理をします。

Slotボタンがマウスで押された時に色と装備を変更するSubmitEquipButtonスクリプトの作成

最後にSlotボタン(4つとも)に新しくSubmitEquipButtonというスクリプトを作成し取りつけます。

スロットボタンが押された時にPressedButtonを実行するように設定してください。
(何度もやってるのでここは省略)

PressdButtonが実行される時はマウスでボタンを押した時です。
その時は先ほど作ったSelectEquipのResetButton関数を呼び出し一旦すべてのボタンの色を白に戻し、その後自身のボタンの色を赤色に設定します。

マウス操作の時も同様にステータスに武器を指定する処理はコメント化しています。

これでゲーム中に表示する装備スロットの処理が完成しました。

ゲーム中の装備スロット機能の確認

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

ステータス画面(キー操作)26

これでゲーム中の装備スロットの表示も完成しました。

これでキーボードやゲームパッドで操作出来るステータス画面の作成が出来ました!!

100記事到達とアクセスアップに感謝

この記事ボリュームありすぎですね・・・・・、分割してもよかったんですが、マウス操作の持ち物画面のように分割すると、色々ページを飛ばなければいけなくなるので面倒くさいと思って全部詰め込みました。

さすがにこれだけ長いと見る気が失せますね・・・・自分自身でも確認が大変です。

一度見直して文章を見なおしましたが大変なんてもんじゃなかったです・・・、プログラムの影響もあるけど文字数が35000文字超えてる記事って・・・(^_^;)

この記事がちょうど100記事目なのでメモリアルという意味も込めてちょうどいい長さなのかもしれません。
4ヶ月目+数日でようやく100記事です。

機能をまず完成させてからでないと記事に出来ないので、記事を書く事より機能を実現するのが大変です((+_+))
更新頻度はどんどん落ちていきそう・・・・(-.-)

ありがたい事に少しづつこのブログのアクセス数も増えてきました。
さらに多くの方に記事を見てもらう機会が増えるとなると過去記事を見直して読みやすくしていく必要がありそうです。

更新はRSSご登録頂いたり、ツイッターで更新情報を流しているのでフォローして頂けると、
更新してないじゃないか!
といった事もなくなるかと思います。

ツイッターは更新情報をツイートする時に使ってるだけです・・・・・・・(-.-)
最近は関係ない事もつぶやく事が多くなりました。

ただツイッターで更新情報をツイートしたけどわたくしのツイート検索出来なかったんですよね・・・
URLが似たようなものだとフィルターにひっかかるのかな?

それでは今後ともよろしく(仲魔?謎)お願いします