今回はコマンド画面にアイテムコマンドを追加していきたいと思います。
機能が複雑なのと、この記事自体が長いので今回はアイテムコマンドをどうやって実現しようとしているか?とスクリプトの中身を把握しながら作って頂けると助かります。
単純に記事も長いのでわかりずらいです。
おそらくコピペで手っ取り早く機能だけ取り付けるというわけにはいかないのでご了承ください。
前回はコマンド画面の作成とステータスコマンドを作成しました。
ユニティちゃんのRPGを作ってみようの他の記事は
から見ることが出来ます。
アイテムコマンドの概要
前回ステータスコマンドを作成したのと同じようにアイテムコマンドを作成していきます。
ただし、アイテムコマンドの場合は
アイテムコマンドの選択→どのキャラクターの持っているアイテムかの選択→アイテム一覧表示→選択したアイテムの種類に応じて装備や使用等の選択→アイテム使用や渡す場合は使用するキャラクターの選択
という流れで条件に応じて新しいパネルをどんどん開く必要があります(昔のドラクエ風)。
今回はパネルを複数作成し、状況に応じてどんどん手前に表示する仕様にしたので、そうなりますが画面全体で情報を表示する場所を決めておき、パネルが重ならないようにするという方法もあります。
UIの作成は上の流れに沿って作成していく事にします。
アイテム一覧は持っているアイテムの種類分のボタンをプレハブからインスタンス化し表示する必要があり、表示領域をスクロールする必要があります。
スクロールバーを用意してマウスでスクロールする場合は問題ないですが、PS3コントローラー等のゲームコントローラーでアイテムを選択する場合は自動でアイテムボタン表示領域をスクロール出来ません。
スクロールバーにフォーカスを移動出来るようにすれば出来ない事もないですが、これはやめておきます。
そこで1回で表示出来るアイテムは何個か決めておいてその表示している最後のボタンの次のボタンを選択したら自動で表示領域がスクロールされるようにします。
現時点では何を言ってんの?と思われるかもしれませんが、アイテム一覧の機能を作った時にわかります。
アイテムコマンドUIやアイテムコマンドの処理が複雑かつ長くなったのでアイテム一覧のスクロール機能は次回作成していきます。
ステータスコマンドの時よりもUIのパネルの数が増えてたり、処理が複雑になっているので注意してください。(´Д`)
エラーが出ないという事は保証しません・・・・(´Д`)
あくまでこういった作り方で出来ましたというわたくしの実験みたいなものです・・・(´Д`)
ですが、あらかじめボタンをヒエラルキー上に配置しておく方法もあります(こちらの方が処理速度が速いかも?)。
やり方に関してはこの記事の最後に記載しますが、既にボタンのプレハブをインスタンス化する方法で作ってしまった為、あらかじめボタンを配置して作る方法を個別に詳細に説明はしません。(´Д`)
アイテムコマンドUIの作成
アイテムコマンドで使用するボタンやパネルを作成していきます。
アイテムコマンドのパネル構成
アイテムコマンドを選択した後のパネルの構成と流れを図にしました。
スクリプトで現在どういう状況なのかを保持しておき、それを元に次のパネルを開いたりCancelボタンを押した時に元のパネルに戻ったりを実行します。
前のパネルで選択したボタンはselectedGameObjectStackにどんどんプッシュしていき、前のパネルに戻った時にポップして取り出し、前のパネルでどのボタンを選択していたかを把握しそのボタンをフォーカスします。
アイテムを選択した状態ではアイテムの使用や渡す、捨てるといったコマンドを表示(UseItemPanel)し、それらを実行した後もそのアイテム数が0より多い場合はそのままUseItemPanelでアイテムをどうするかを選択します。
UseItemPanelの捨てるを選択した時やアイテムを使用や渡す相手を選択するUseItemSelectCharacterPanelでキャラクターを選択した後にそのアイテムが0になり、かつそのキャラクターが他のアイテムも一つも持っていない場合はSelectCharacterPanelに処理を移します。
そのアイテム自体がなくなっても他のアイテムを持っていればItemPanelに戻ります。
アイテムコマンドボタンの作成
アイテムコマンドを実行する為のボタンを作成します。
Command→CommandPanelの子要素のStatusButtonを選択し、Ctrl+Dキーで複製し名前をItemButtonとします。
ItemButtonのButtonのOn ClickでCommandScriptのSelectCommandメソッドを呼び出した時の引数はItemに変更します。
ItemButtonを押した時はCommandScriptのSelectCommandでアイテムコマンドの処理がされるように後で処理を追加します。
ItemButtonの子要素のTextのインスペクタでTextにアイテムと入力します。
アイテムを表示するキャラクター選択パネルの作成
ItemButtonを押したら次はどのキャラクターのアイテムを表示するかのパネルを表示する必要があります。
これはステータスコマンドでどのキャラクターのステータスを表示するか?というSelectCharacterPanelと同じなのでSelectCharacterPanelを使用することにします。
アイテム一覧表示パネルの作成
どのキャラクターのアイテムを表示するかのボタンを押したら次はそのキャラクターが持つアイテムの一覧とアイテム数等を表示するアイテム一覧パネルを表示する必要があります。
Commandゲームオブジェクトを選択した状態で右クリックからUI→Panelを選択しItemPanelという名前にします。
ItemPanelのサイズは
上のような感じにしました。
ItemPanelのImageコンポーネントの横のチェックを外し、表示しないようにします。
ItemPanelのインスペクタについては後で変更しますので、その時に画像で設定を紹介します。
アイテム一覧のマスク領域の作成
ItemPanelを選択した状態で右クリックからUI→Panelを選択し、名前をMaskとします。
MaskのインスペクタのAdd ComponentからUI→Maskを選択し取り付けます。
このMaskゲームオブジェクトはMaskコンポーネントを取り付けているので子要素のアイテムボタンやテキスト等が範囲外(Mask領域外)に出た時は表示されなくなります。
アイテムパネルボタンを表示する領域の作成
Maskを選択した状態で右クリックからUI→Panelを選択し、名前をContentとします。
Anchor Presetsからtop stretchにし開始位置はMaskの上、横幅はMaskの幅にし、Heightを3000としておきます。
Heightの値はアイテム一覧全体の長さになるので、アイテムを表示する数に応じて数値をより大きくする必要があります。
ContentのインスペクタのAdd ComponentからLayout→Grid Layout Groupを取り付け以下のように設定します。
Grid Layout Groupはグリッドで子要素のコンテンツを整列させることが出来ます。
Cell Sizeで子要素のゲームオブジェクト(個々のアイテムボタン)のサイズを設定し、ConstraintsでFixed Column Countに設定し、Countを2にして横に2個アイテムボタンを表示したら下に表示するようにします。
個々のアイテムを表すItemPanelButtonプレハブの作成
Contentの子要素に配置する個々のアイテムを表すItemPanelButtonプレハブを作成していきます。
Contentを選択した状態で右クリックからUI→Buttonを選択し、名前をItemPanelButtonとします。
Imageのチェックを外し、ButtonのTransitionをNoneにします。
ItemPanelButtonも選択した時に音を鳴らしたいのでCommandPanelButtonScriptとAudio Sourceコンポーネントを取り付け鳴らす音をAudio Clipに設定します。
さらにHorizontal Layout Groupコンポーネントも取り付け、Child AlignmentをMiddle Centerにします。
また新しくItemPanelButtonScriptスクリプトを作成し取り付けます。
ItemPanelButtonにHorizontal Layout Groupコンポーネントを取り付けたので子要素のUIの要素が横に整列します。
ItemPanelButtonScriptは以下のように作成します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.UI; public class ItemPanelButtonScript : MonoBehaviour, ISelectHandler { private Item item; // アイテムタイトル表示テキスト private Text itemTitleText; // アイテム情報表示テキスト private Text itemInformationText; private void Awake() { itemTitleText = transform.root.Find("ItemInformationPanel/Title").GetComponent<Text>(); itemInformationText = transform.root.Find("ItemInformationPanel/Information").GetComponent<Text>(); } // ボタンが選択された時に実行 public void OnSelect(BaseEventData eventData) { ShowItemInformation(); } // アイテム情報の表示 public void ShowItemInformation() { itemTitleText.text = item.GetKanjiName(); itemInformationText.text = item.GetInformation(); } // データをセットする public void SetParam(Item item) { this.item = item; } } |
SetParamメソッドはCommandScriptメソッドから呼び出してアイテムボタン個々でアイテム情報を保持し、アイテムパネルボタンが選択されたらアイテム情報を表示します。
ItemPanelButtonの子要素にUIのImageとTextを4つ作成し、Textの名前をEquip、ItemName、Multiply、Numと変更します。
4つのTextのFont Sizeは25にします。
Imageはボタンを選択した時のアイコンの設定でStatusButtonやItemButtonと同じです。
Equipは装備している武器や鎧である場合にEを表示するのに使い、ItemNameはアイテム名、Multiplyはアイテムの個数を表す×を表示し、Numにはアイテムの個数を表示します。
Equip、MultiplyのAlignmentは中央にし、ItemNameは左揃え、Numは右揃えにしておきます。
ItemPanelButtonは親のContentのGrid Layout Groupでセルのサイズを指定しているので、Widthを300、Heightを50にし、子要素のImageやテキスト群はそれに合わせてWidthとHeightを調整したり位置を調整してください。
わたくしの場合はImageのWidthとHeightを30にし、それ以外のText群のHeightは50に固定で、EquipのWidthは30、ItemNameのWidthは140、MultiplyのWidthは20、NumのWidthは50にしてみました。
配置としては以下のようになります。
EquipのTextコンポーネントのTextは空にしておきます。
ここまで出来たらItemPanelButtonをAssets/RPG/Prefabs/UI/Commandフォルダ内にドラッグ&ドロップしてプレハブにします。
ヒエラルキー上のItemPanelButtonはこの後使いますので残しておきます。
アイテムパネルボタンをとりあえず並べてみる
アイテムパネルボタンがどのように表示されるかを確認する為に、ヒエラルキー上のItemPanelButtonをCtrl+Dキーで複製し20個に増やしてみます。
するとシーンビューでは以下のように表示されます。
アイテムが表示されるのはMaskパネルの領域だけなのでアイテムボタンが16個までしか表示されず、その下のアイテムボタンは見えません(ItemPanelのサイズによって数は変わります)。
また表示されている15個目と16個目のアイテムボタンは少し切れています。
そこでMaskパネルの領域を少し狭めてアイテムが14個まで完全に表示される状態にします。
これでとりあえず1回に見える範囲は14個のアイテムだけになりました。
アイテム一覧をマウスでスクロール出来るようにする
アイテム一覧をマウススクロールするにはScroll RectコンポーネントとScrollbarが必要になります。
ItemPanelのインスペクタでAdd ComponentからUI→Scroll RectとLayout→Canvas Groupを取り付けます。
ItemPanelを選択した状態で右クリックからUI→Scrollbarを選択します。
ScrollbarのRect TransformのAnchor Presetsでmiddle rightにしWidthを20、Heightを160とします(WidthとHeightは任意です)。
ScrollbarのDirectionをBottom To TopにしValueを1とします。
次にItemPanelに取り付けたScroll Rectコンポーネントの設定をします。
ContentにはMaskの子要素のContentゲームオブジェクトを設定し、Movement TypeをClampedにします。ClampedにするとContentゲームオブジェクトの子要素のアイテムボタンの表示領域で制限されて動きます。
マウスでスクロールする場合はContentの領域内で動きます。
Vertical Scrollbarに先ほど作ったScrollbarゲームオブジェクトを設定します。
上ではCanvas Groupのinteractableのチェックを外していますが、これはスクリプトから有効と無効を切り替えるので最初は無効としておく必要があります。
ただ今はマウスでスクロールするのを確認したいのでinteractableにチェックを入れます。
これでContent領域をマウスでドラッグしたり、スクロールバーをドラッグすることでアイテム一覧の領域を移動出来るようになりました。
ただ、ゲームコントローラーでアイテムを選択して下に移動していってもアイテム一覧はスクロールしてくれません。
とりあえずゲームコントローラーでアイテム一覧をスクロールするやり方は次回作成するので、UIの続きを作成していきましょう。
ItemPanel子要素のContent以下に作成したItemPanelButton達は全て削除し、Content以下には何もゲームオブジェクトがないようにします。
またItemPanelのCanvas Groupのinteractableのチェックを外しておきます。
アイテムを選択した時に表示するパネルの作成
アイテム一覧パネルでアイテムボタンを押した時に表示するパネルを作成します。
Commandを選択した状態で右クリック→Panelを選択し、名前をUseItemPanelとします。
表示領域は以下のようにしました。
UseItemPanelのインスペクタのAdd CompoenntからLayout→Canvas GroupとLayout→Vertical Group Layoutを取り付けます。
設定については今まで作成してきたパネルと同じです。
次にUseItemPanelの子要素にAssets/RPG/Prefabs/UI/Command/CharacterButtonをドラッグ&ドロップします。
今ドラッグ&ドロップしたCharacterButtonを選択した状態で右クリックからUnpack Prefab Completelyを選択しプレハブとのリンクを解除し普通のゲームオブジェクトにします。
そしたら名前をUseItemButtonとし、Assets/RPG/Prefabs/UI/Commandフォルダにドラッグ&ドロップしてプレハブにします。
プレハブにしたらヒエラルキー上のUseItemButtonは削除します。
アイテムを使うキャラクター選択パネルの作成
次にアイテムを選択した時に表示したパネル(UseItemPanel)で『使う』や『渡す』を選択した時に表示する誰にアイテムを使うのか?を表示するパネルを作成します。
UseItemPanelゲームオブジェクトを選択しCtrl+Dキーで複製し、名前をUseItemSelectCharacterPanelとします。
UseItemSelectCharacterPanelの領域は以下のようにしました。
UseItemSelectCharacterPanelに表示するボタンはSelectCharacterPanelと同じCharacterButtonなので特に作成しません。
アイテム情報の情報を表示するパネルの作成
アイテム情報を表示するパネルを作成していきます。
Commandを選択した状態で右クリックからUI→Panelを選択し、名前をItemInformationPanelとします。
ItemInformationPanelの子要素にUI→Textを二つ作成し、名前をTitleとInformationにし、以下のような領域にします。
Titleにはアイテムのタイトル、Informationにはアイテム情報やアイテムを使用した時の情報を表示します。
TitleとInformationのFont Sizeは25にしました。
アイテムの装備や使用等をした時の情報表示パネルの作成
アイテムの装備や使用等をした時にもItemInformationPanelのInformationのテキストに表示しようと思ったんですが、ItemPanelButtonScriptでボタンが選択された時にアイテム情報を更新しているので、これがうまく出来ません。
そこでアイテムを装備や使用した時は別のパネルを作りそこに情報を表示しようと思います。
Commandを選択した状態で右クリックからUI→Panelを選択しUseItemInformationPanelとし子要素にUI→Textを作成します。
TextのAnchor Presetsでstretch stretchにしUseItemInformationPanelの大きさに応じてTextの幅も変えます。
TextのFont Sizeは30にしました。
AlignmentはMiddle Centerにします。
UseItemInformationPanelは以下のような位置とサイズにしました。
これでアイテムコマンドに関するUIの作成が完了しました。
CommandScriptにアイテムコマンドの処理を追加する
UIが出来たので後はItemButtonを押した後のアイテムコマンドの処理をCommandScriptに追加していくだけです。
追加していくだけですと言うと簡単なように思えますが、処理は面倒な事をしています。(^_^;)
CommandModeにモードを追加する
まずはCommandModeにモードを追加します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | public enum CommandMode { CommandPanel, StatusPanelSelectCharacter, StatusPanel, ItemPanelSelectCharacter, ItemPanel, UseItemPanel, UseItemSelectCharacterPanel, UseItemPanelToItemPanel, UseItemPanelToUseItemPanel, UseItemSelectCharacterPanelToUseItemPanel, NoItemPassed } |
になります。
フィールド宣言
フィールドを追加します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | // アイテム表示パネル private GameObject itemPanel; // アイテムパネルボタンを表示する場所 private GameObject content; // アイテムを使う選択パネル private GameObject useItemPanel; // アイテムを使う相手を誰にするか選択するパネル private GameObject useItemSelectCharacterPanel; // 情報表示パネル private GameObject itemInformationPanel; // アイテム使用後の情報表示パネル private GameObject useItemInformationPanel; // アイテムパネルのCanvas Group private CanvasGroup itemPanelCanvasGroup; // アイテムを使う選択パネルのCanvasGroup private CanvasGroup useItemPanelCanvasGroup; // アイテムを使うキャラクター選択パネルのCanvasGroup; private CanvasGroup useItemSelectCharacterPanelCanvasGroup; // 情報表示タイトルテキスト private Text informationTitleText; // 情報表示テキスト private Text informationText; // キャラクターアイテムのボタンのプレハブ [SerializeField] private GameObject itemPanelButtonPrefab = null; // アイテム使用時のボタンのプレハブ [SerializeField] private GameObject useItemPanelButtonPrefab = null; // アイテムボタン一覧 private List<GameObject> itemPanelButtonList = new List<GameObject>(); |
作成したパネルのフィールドやテキスト、アイテムボタンや使用するアイテムのボタンのプレハブを作りプレハブにはインスペクタで設定する必要があります。
itemPanelButtonListにはアイテム一覧に表示したボタンのゲームオブジェクトを登録しておき、武器を装備した時や外した時にアイテムの名前の前のEquipを表すEの文字を表示したり消したりする時に使用します。
Awakeメソッドに処理を追加
Awakeメソッドにフィールドに設定するゲームオブジェクト等の取得をする処理を追加します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | itemPanel = transform.Find("ItemPanel").gameObject; content = itemPanel.transform.Find("Mask/Content").gameObject; useItemPanel = transform.Find("UseItemPanel").gameObject; useItemSelectCharacterPanel = transform.Find("UseItemSelectCharacterPanel").gameObject; itemInformationPanel = transform.Find("ItemInformationPanel").gameObject; useItemInformationPanel = transform.Find("UseItemInformationPanel").gameObject; itemPanelCanvasGroup = itemPanel.GetComponent<CanvasGroup>(); useItemPanelCanvasGroup = useItemPanel.GetComponent<CanvasGroup>(); useItemSelectCharacterPanelCanvasGroup = useItemSelectCharacterPanel.GetComponent<CanvasGroup>(); // 情報表示用テキスト informationTitleText = itemInformationPanel.transform.Find("Title").GetComponent<Text>(); informationText = itemInformationPanel.transform.Find("Information").GetComponent<Text>(); |
行っていることは階層を辿って該当するゲームオブジェクト、CanvasGroup、Textを取得しているだけです。
OnEnableメソッドに処理を追加
OnEnableメソッドにパネルの非表示等の処理を追加します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | itemPanel.SetActive(false); useItemPanel.SetActive(false); useItemSelectCharacterPanel.SetActive(false); itemInformationPanel.SetActive(false); useItemInformationPanel.SetActive(false); // アイテムパネルボタンがあれば全て削除 for (int i = content.transform.childCount - 1; i >= 0; i--) { Destroy(content.transform.GetChild(i).gameObject); } // アイテムを使うキャラクター選択ボタンがあれば全て削除 for (int i = useItemPanel.transform.childCount - 1; i >= 0; i--) { Destroy(useItemPanel.transform.GetChild(i).gameObject); } // アイテムを使う相手のキャラクター選択ボタンがあれば全て削除 for (int i = useItemSelectCharacterPanel.transform.childCount - 1; i >= 0; i--) { Destroy(useItemSelectCharacterPanel.transform.GetChild(i).gameObject); } itemPanelButtonList.Clear(); itemPanelCanvasGroup.interactable = false; useItemPanelCanvasGroup.interactable = false; useItemSelectCharacterPanelCanvasGroup.interactable = false; |
Commandがアクティブになった時に以前作成したボタンの削除、リストのクリア、CanvasGroupの初期化を行っています。
Updateメソッドに処理を追加する
Updateメソッドに処理を追加していきます。
Cancelボタンを押した時の処理
UpdateメソッドでCancelボタンが押された時に現在どのコマンドモードかを調べ処理を分岐させている所に新しく追加した状態の条件を加えます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 | // どのキャラクターのアイテムを表示するかの選択時 } else if (currentCommand == CommandMode.ItemPanelSelectCharacter) { selectCharacterPanelCanvasGroup.interactable = false; selectCharacterPanel.SetActive(false); itemInformationPanel.SetActive(false); for (int i = selectCharacterPanel.transform.childCount - 1; i >= 0; i--) { Destroy(selectCharacterPanel.transform.GetChild(i).gameObject); } EventSystem.current.SetSelectedGameObject(selectedGameObjectStack.Pop()); commandPanelCanvasGroup.interactable = true; currentCommand = CommandMode.CommandPanel; // アイテム一覧表示時 } else if (currentCommand == CommandMode.ItemPanel) { itemPanelCanvasGroup.interactable = false; itemPanel.SetActive(false); itemInformationPanel.SetActive(false); // リストをクリア itemPanelButtonList.Clear(); // ItemPanelでCancelを押したらcontent以下のアイテムパネルボタンを全削除 for (int i = content.transform.childCount - 1; i >= 0; i--) { Destroy(content.transform.GetChild(i).gameObject); } EventSystem.current.SetSelectedGameObject(selectedGameObjectStack.Pop()); selectCharacterPanelCanvasGroup.interactable = true; currentCommand = CommandMode.ItemPanelSelectCharacter; // アイテムを選択し、どう使うかを選択している時 } else if (currentCommand == CommandMode.UseItemPanel) { useItemPanelCanvasGroup.interactable = false; useItemPanel.SetActive(false); // UseItemPanelでCancelボタンを押したらUseItemPanelの子要素のボタンの全削除 for (int i = useItemPanel.transform.childCount - 1; i >= 0; i--) { Destroy(useItemPanel.transform.GetChild(i).gameObject); } EventSystem.current.SetSelectedGameObject(selectedGameObjectStack.Pop()); itemPanelCanvasGroup.interactable = true; currentCommand = CommandMode.ItemPanel; // アイテムを使用する相手のキャラクターを選択している時 } else if (currentCommand == CommandMode.UseItemSelectCharacterPanel) { useItemSelectCharacterPanelCanvasGroup.interactable = false; useItemSelectCharacterPanel.SetActive(false); // UseItemSelectCharacterPanelでCancelボタンを押したらアイテムを使用するキャラクターボタンの全削除 for (int i = useItemSelectCharacterPanel.transform.childCount - 1; i >= 0; i--) { Destroy(useItemSelectCharacterPanel.transform.GetChild(i).gameObject); } EventSystem.current.SetSelectedGameObject(selectedGameObjectStack.Pop()); useItemPanelCanvasGroup.interactable = true; currentCommand = CommandMode.UseItemPanel; } |
やっていることは同じなので割愛します。
ほとんど同じ処理をしているのでメソッドに切り分けることも出来そうです。
が、ややこしくなるので同じような記述をズラズラと書いています。
アイテム使用後の情報を消し次の事を行う為の処理
アイテムを装備、装備を外す、使用、渡す、捨てるといった事を行ったらUseItemInformationPanelの子要素のTextに何をしたか?の情報を載せます。
その情報を載せた状態で何らかのキーを押した時に次の動作に移行させる為の処理を記述します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 | // アイテムを装備、装備を外す情報表示後の処理 if (currentCommand == CommandMode.UseItemPanelToItemPanel) { if (Input.anyKeyDown || !Mathf.Approximately(Input.GetAxis("Horizontal"), 0f) || !Mathf.Approximately(Input.GetAxis("Vertical"), 0f) ) { currentCommand = CommandMode.ItemPanel; useItemInformationPanel.SetActive(false); itemPanel.transform.SetAsLastSibling(); itemPanelCanvasGroup.interactable = true; EventSystem.current.SetSelectedGameObject(selectedGameObjectStack.Pop()); } // アイテムを使用する相手のキャラクター選択からアイテムをどうするかに移行する時 } else if (currentCommand == CommandMode.UseItemSelectCharacterPanelToUseItemPanel) { if (Input.anyKeyDown || !Mathf.Approximately(Input.GetAxis("Horizontal"), 0f) || !Mathf.Approximately(Input.GetAxis("Vertical"), 0f) ) { currentCommand = CommandMode.UseItemPanel; useItemInformationPanel.SetActive(false); useItemPanel.transform.SetAsLastSibling(); useItemPanelCanvasGroup.interactable = true; EventSystem.current.SetSelectedGameObject(selectedGameObjectStack.Pop()); } // アイテムを捨てるを選択した後の状態 } else if (currentCommand == CommandMode.UseItemPanelToUseItemPanel) { if (Input.anyKeyDown || !Mathf.Approximately(Input.GetAxis("Horizontal"), 0f) || !Mathf.Approximately(Input.GetAxis("Vertical"), 0f) ) { currentCommand = CommandMode.UseItemPanel; useItemInformationPanel.SetActive(false); useItemPanel.transform.SetAsLastSibling(); useItemPanelCanvasGroup.interactable = true; } // アイテムを使用、渡す、捨てるを選択した後にそのアイテムの数が0になった時 } else if (currentCommand == CommandMode.NoItemPassed) { if (Input.anyKeyDown || !Mathf.Approximately(Input.GetAxis("Horizontal"), 0f) || !Mathf.Approximately(Input.GetAxis("Vertical"), 0f) ) { currentCommand = CommandMode.ItemPanel; useItemInformationPanel.SetActive(false); useItemPanel.SetActive(false); itemPanel.transform.SetAsLastSibling(); itemPanelCanvasGroup.interactable = true; // アイテムパネルボタンがあれば最初のアイテムパネルボタンを選択 if (content.transform.childCount != 0) { EventSystem.current.SetSelectedGameObject(content.transform.GetChild(0).gameObject); } else { // アイテムパネルボタンがなければ(アイテムを持っていない)ItemSelectPanelに戻る currentCommand = CommandMode.ItemPanelSelectCharacter; itemPanelCanvasGroup.interactable = false; itemPanel.SetActive(false); selectCharacterPanelCanvasGroup.interactable = true; selectCharacterPanel.SetActive(true); EventSystem.current.SetSelectedGameObject(selectedGameObjectStack.Pop()); } } } |
アイテムをどうするか?をUseItemPanelで選択した後にどうしたのか?の情報をUseItemInformationPanelに表示していますが、その後に何らかのキーを押したらUseItemInformationPanelを非表示にしてから次の行動が出来るようにしています。
currendCommandの状態に応じてキーが押されたらどのパネルのCanvasGroupのinteractableを操作して、どのパネルをアクティブにするか等の処理をしています。
Input.anyKeyDownはUnityメニューのEdit→Project Settings→InputのTypeでKey or Mouse Buttonであるボタンが押された時、キーボードのキーを押した時マウスボタンを押した時等にtrueになります。
なのでゲームコントローラーのジョイスティックや十字キー等のInputのTypeがJoystick Axisの場合は反応しません。
そういったものも反映させる為に!Mathf.Approximately(Input.GetAxis(“Horizontal”), 0f)等の条件を加えて、十字キーやジョイスティックが少しでも押されていたら条件が成立するようにしています。
SelectCommandメソッドに処理を追加する
SelectCommandにItemButtonを押した時に処理をする部分を追加します。
SelectCommandはCommandPanelのボタンが押された時の処理をしていました。
送られてきた文字列がStatusの時のif分の下にItemの時の処理を追加します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | } else if (command == "Item") { currentCommand = CommandMode.ItemPanelSelectCharacter; statusPanel.SetActive(false); commandPanelCanvasGroup.interactable = false; selectedGameObjectStack.Push(EventSystem.current.currentSelectedGameObject); GameObject characterButtonIns; // パーティメンバー分のボタンを作成 foreach (var member in partyStatus.GetAllyStatus()) { characterButtonIns = Instantiate<GameObject>(characterPanelButtonPrefab, selectCharacterPanel.transform); characterButtonIns.GetComponentInChildren<Text>().text = member.GetCharacterName(); characterButtonIns.GetComponent<Button>().onClick.AddListener(() => CreateItemPanelButton(member)); } } |
行っていることはStatusの時とほとんど同じで作成したボタンが押された時にCreateItemPanelButtonメソッドを呼び出すだけです。
AddListenerの引数にはラムダ式を指定し、ボタンがクリックされたら無条件にCreateItemPanelButtonメソッドに引数memberを渡して呼び出します。
ラムダ式については
を参照してください。
CreateItemPanelButtonメソッドの作成
CreateItemPanelButtonメソッドはどのキャラクターのアイテムを表示するかのボタンを押した時に実行されるメソッドです。
どのキャラクターのアイテムを表示するかの選択がされた後の処理なのでItemPanelを表示し、そこに個々のアイテムを表すItemPanelButtonプレハブからインスタンスを生成していきます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | // キャラクターが持っているアイテムのボタン表示 public void CreateItemPanelButton(AllyStatus allyStatus) { itemInformationPanel.SetActive(true); selectCharacterPanelCanvasGroup.interactable = false; // アイテムパネルボタンを何個作成したかどうか int itemPanelButtonNum = 0; GameObject itemButtonIns; // 選択したキャラクターのアイテム数分アイテムパネルボタンを作成 // 持っているアイテム分のボタンの作成とクリック時の実行メソッドの設定 foreach (var item in allyStatus.GetItemDictionary().Keys) { itemButtonIns = Instantiate<GameObject>(itemPanelButtonPrefab, content.transform); itemButtonIns.transform.Find("ItemName").GetComponent<Text>().text = item.GetKanjiName(); itemButtonIns.GetComponent<Button>().onClick.AddListener(() => SelectItem(allyStatus, item)); itemButtonIns.GetComponent<ItemPanelButtonScript>().SetParam(item); // アイテム数を表示 itemButtonIns.transform.Find("Num").GetComponent<Text>().text = allyStatus.GetItemNum(item).ToString(); // 装備している武器や防具には名前の前にEを表示し、そのTextを保持して置く if (allyStatus.GetEquipWeapon() == item) { itemButtonIns.transform.Find("Equip").GetComponent<Text>().text = "E"; } else if (allyStatus.GetEquipArmor() == item) { itemButtonIns.transform.Find("Equip").GetComponent<Text>().text = "E"; } // アイテムボタンリストに追加 itemPanelButtonList.Add(itemButtonIns); // アイテムパネルボタン番号を更新 itemPanelButtonNum++; } // アイテムパネルの表示と最初のアイテムの選択 if (content.transform.childCount != 0) { // SelectCharacerPanelで最後にどのゲームオブジェクトを選択していたか selectedGameObjectStack.Push(EventSystem.current.currentSelectedGameObject); currentCommand = CommandMode.ItemPanel; itemPanel.SetActive(true); itemPanel.transform.SetAsLastSibling(); itemPanelCanvasGroup.interactable = true; EventSystem.current.SetSelectedGameObject(content.transform.GetChild(0).gameObject); } else { informationTitleText.text = ""; informationText.text = "アイテムを持っていません。"; selectCharacterPanelCanvasGroup.interactable = true; } } |
アイテム一覧を表示するのでitemInformationPanelを表示し、アイテムを選択した時にそのアイテムの情報を見れるようにします。
前のパネルのCanvasGroupであるselectCharacterPanelCanvasGroupはfalseにしSelectCharacterPanelのボタンは選択出来ないようにします。
allyStatus.GetItemDictionary().Keysでそのキャラクターが持っているアイテムのキーが全て取得出来るのでforeachを使って全部のアイテムのボタンを作成していきます。
ItemPanelButtonPrefabはItemPanelの子要素のContentゲームオブジェクトの子要素としてインスタンス化します。
インスタンス化したボタンの子要素からItemNameという名前のゲームオブジェクトのTextコンポーネントを取得し、item.GetKanjiName()でアイテムの漢字名を取得し入れています。
アイテム一覧にインスタンス化したアイテムパネルボタンが押された時はそのアイテムについて何らかの行動をする必要がありそれを設定しているのが、
1 2 3 | itemButtonIns.GetComponent<Button>().onClick.AddListener(() => SelectItem(allyStatus, item)); |
の処理です。
今プレハブからインスタンス化したItemPanelButtonPrefabのButtonコンポーネントを取得しonClick(ボタンを押した時)にAddListenerメソッドを使って実行するメソッドを登録しています。
アイテムパネルボタンを押した時はSelectItemメソッドに引数allyStatus(そのキャラクターのステータス)とitem(このボタンを表しているアイテム)を渡します。
ItemPanelButtonPrefabにはあらかじめItemPanelButtonScriptを取り付けてあるのでSetParamメソッドを使ってItemを渡しています。
アイテムパネルボタンにはアイテムの数とそのアイテムが装備している武器や鎧だった時はEを表示する箇所があるので、情報を取得してそれを設定しています。
アイテムパネルボタンのインスタンスが出来たらitemPanelButtonListに登録しておきます。
アイテム一覧にアイテム数分のアイテムパネルボタンが出来たらContentの最初の子要素を選択している状態にします。
もしキャラクターがアイテムをひとつも持っていなければ情報を表示し、SelectCharacterPanelに戻ります。
SelectItemメソッドの作成
次にアイテム一覧に表示した個々のアイテムボタンを押された時に実行するSelectItemメソッドを作成していきます。
SelectItemメソッドではそのアイテムに対してどういった操作が可能かを判断しUseItemPanelに対応するボタンを作成します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 | // アイテムをどうするかの選択 public void SelectItem(AllyStatus allyStatus, Item item) { // アイテムの種類に応じて出来る項目を変更する if (item.GetItemType() == Item.Type.ArmorAll || item.GetItemType() == Item.Type.ArmorUnityChan || item.GetItemType() == Item.Type.ArmorYuji || item.GetItemType() == Item.Type.WeaponAll || item.GetItemType() == Item.Type.WeaponUnityChan || item.GetItemType() == Item.Type.WeaponYuji) { var itemMenuButtonIns = Instantiate<GameObject>(useItemPanelButtonPrefab, useItemPanel.transform); if (item == allyStatus.GetEquipWeapon() || item == allyStatus.GetEquipArmor()) { itemMenuButtonIns.GetComponentInChildren<Text>().text = "装備を外す"; itemMenuButtonIns.GetComponent<Button>().onClick.AddListener(() => RemoveEquip(allyStatus, item)); } else { itemMenuButtonIns.GetComponentInChildren<Text>().text = "装備する"; itemMenuButtonIns.GetComponent<Button>().onClick.AddListener(() => Equip(allyStatus, item)); } itemMenuButtonIns = Instantiate<GameObject>(useItemPanelButtonPrefab, useItemPanel.transform); itemMenuButtonIns.GetComponentInChildren<Text>().text = "渡す"; itemMenuButtonIns.GetComponent<Button>().onClick.AddListener(() => PassItem(allyStatus, item)); itemMenuButtonIns = Instantiate<GameObject>(useItemPanelButtonPrefab, useItemPanel.transform); itemMenuButtonIns.GetComponentInChildren<Text>().text = "捨てる"; itemMenuButtonIns.GetComponent<Button>().onClick.AddListener(() => ThrowAwayItem(allyStatus, item)); } else if (item.GetItemType() == Item.Type.NumbnessRecovery || item.GetItemType() == Item.Type.PoisonRecovery || item.GetItemType() == Item.Type.HPRecovery || item.GetItemType() == Item.Type.MPRecovery ) { var itemMenuButtonIns = Instantiate<GameObject>(useItemPanelButtonPrefab, useItemPanel.transform); itemMenuButtonIns.GetComponentInChildren<Text>().text = "使う"; itemMenuButtonIns.GetComponent<Button>().onClick.AddListener(() => UseItem(allyStatus, item)); itemMenuButtonIns = Instantiate<GameObject>(useItemPanelButtonPrefab, useItemPanel.transform); itemMenuButtonIns.GetComponentInChildren<Text>().text = "渡す"; itemMenuButtonIns.GetComponent<Button>().onClick.AddListener(() => PassItem(allyStatus, item)); itemMenuButtonIns = Instantiate<GameObject>(useItemPanelButtonPrefab, useItemPanel.transform); itemMenuButtonIns.GetComponentInChildren<Text>().text = "捨てる"; itemMenuButtonIns.GetComponent<Button>().onClick.AddListener(() => ThrowAwayItem(allyStatus, item)); } else if (item.GetItemType() == Item.Type.Valuables) { informationTitleText.text = item.GetKanjiName(); informationText.text = item.GetInformation(); } if (item.GetItemType() != Item.Type.Valuables) { useItemPanel.SetActive(true); itemPanelCanvasGroup.interactable = false; currentCommand = CommandMode.UseItemPanel; // ItemPanelで最後にどれを選択していたか? selectedGameObjectStack.Push(EventSystem.current.currentSelectedGameObject); useItemPanel.transform.SetAsLastSibling(); EventSystem.current.SetSelectedGameObject(useItemPanel.transform.GetChild(0).gameObject); useItemPanelCanvasGroup.interactable = true; Input.ResetInputAxes(); } } |
アイテムの種類に応じて選択出来る項目のタイトルやボタンを押された時に実行するメソッドの設定を変えています。
アイテムが装備品の場合で既に装備している装備品であれば『装備を外す』(RemoveEquipメソッド)、装備していなければ『装備する』(Equipメソッド)、『渡す』(PassItemメソッド)『捨てる』(ThrowAwayItemメソッド)をぞれぞれ実行します。
回復アイテム(Item.Type.HPRecovery、Item.Type.MPRecovery)、状態回復アイテム(Item.Type.NumbnessRecovery、Item.Type.PoisonRecovery)の場合は『使う』(UseItemメソッド)、『渡す』『捨てる』ボタンを表示します。
貴重品(Item.Type.Valuables)の場合は情報表示パネルにアイテム情報を表示するだけです。
貴重品以外のアイテムであればcurrentCommandを変更し、現在選択しているボタンをselectedGameObjectStackにプッシュし、UseItemPanelの最初のボタンを選択状態にします。
Input.ResetInputAxes()メソッドはそのフレームでの入力をリセットし同じフレーム内で連続してキーやボタンが押されたと判断されない為に入れています。
UseItemメソッドの作成
選択したアイテムをどうするか?の『使う』ボタンを押した時に実行するUseItemメソッドを作成していきます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | // アイテムを使用するキャラクターを選択する public void UseItem(AllyStatus allyStatus, Item item) { useItemPanelCanvasGroup.interactable = false; useItemSelectCharacterPanel.SetActive(true); // UseItemPanelでどれを最後に選択していたか selectedGameObjectStack.Push(EventSystem.current.currentSelectedGameObject); GameObject characterButtonIns; // パーティメンバー分のボタンを作成 foreach (var member in partyStatus.GetAllyStatus()) { characterButtonIns = Instantiate<GameObject>(characterPanelButtonPrefab, useItemSelectCharacterPanel.transform); characterButtonIns.GetComponentInChildren<Text>().text = member.GetCharacterName(); characterButtonIns.GetComponent<Button>().onClick.AddListener(() => UseItemToCharacter(allyStatus, member, item)); } // UseItemSelectCharacterPanelに移行する currentCommand = CommandMode.UseItemSelectCharacterPanel; useItemSelectCharacterPanel.transform.SetAsLastSibling(); EventSystem.current.SetSelectedGameObject(useItemSelectCharacterPanel.transform.GetChild(0).gameObject); useItemSelectCharacterPanelCanvasGroup.interactable = true; Input.ResetInputAxes(); } |
選択したアイテムを『使う』という選択をしたので、現在選択している『使う』ボタンをselectedGameObjectStackにプッシュし、UseItemSelectCharacterPanelにパーティーメンバー分のボタンをプレハブからインスタンス化し、そのボタンが押された時にUseItemToCharacterメソッドが実行されるようにします。
アイテムを使う事にしたので誰に使うか?のボタンを表示するUseItemSelectCharacterPanelの子要素に表示するボタンの作成とそのボタンを押した時に実行するメソッドを指定しています。
UseItemToCharacterメソッドの作成
アイテムを使うキャラクターを選択した時に実行するUseItemToCharacterメソッドを作成します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 | public void UseItemToCharacter(AllyStatus fromChara, AllyStatus toChara, Item item) { useItemInformationPanel.SetActive(true); useItemSelectCharacterPanelCanvasGroup.interactable = false; useItemSelectCharacterPanel.SetActive(false); if (item.GetItemType() == Item.Type.HPRecovery) { if (toChara.GetHp() == toChara.GetMaxHp()) { useItemInformationPanel.GetComponentInChildren<Text>().text = toChara.GetCharacterName() + "は元気です。"; } else { toChara.SetHp(toChara.GetHp() + item.GetAmount()); // アイテムを使用した旨を表示 useItemInformationPanel.GetComponentInChildren<Text>().text = fromChara.GetCharacterName() + "は" + item.GetKanjiName() + "を" + toChara.GetCharacterName() + "に使用しました。\n" + toChara.GetCharacterName() + "は" + item.GetAmount() + "回復しました。"; // 持っているアイテム数を減らす fromChara.SetItemNum(item, fromChara.GetItemNum(item) - 1); } } else if(item.GetItemType() == Item.Type.MPRecovery) { if (toChara.GetMp() == toChara.GetMaxMp()) { useItemInformationPanel.GetComponentInChildren<Text>().text = toChara.GetCharacterName() + "のMPは最大です。"; } else { toChara.SetMp(toChara.GetMp() + item.GetAmount()); // アイテムを使用した旨を表示 useItemInformationPanel.GetComponentInChildren<Text>().text = fromChara.GetCharacterName() + "は" + item.GetKanjiName() + "を" + toChara.GetCharacterName() + "に使用しました。\n" + toChara.GetCharacterName() + "はMPを" + item.GetAmount() + "回復しました。"; // 持っているアイテム数を減らす fromChara.SetItemNum(item, fromChara.GetItemNum(item) - 1); } } else if (item.GetItemType() == Item.Type.PoisonRecovery) { if (!toChara.IsPoisonState()) { useItemInformationPanel.GetComponentInChildren<Text>().text = toChara.GetCharacterName() + "は毒状態ではありません。"; } else { useItemInformationPanel.GetComponentInChildren<Text>().text = toChara.GetCharacterName() + "は毒から回復しました。"; toChara.SetPoisonState(false); // 持っているアイテム数を減らす fromChara.SetItemNum(item, fromChara.GetItemNum(item) - 1); } } else if (item.GetItemType() == Item.Type.NumbnessRecovery) { if (!toChara.IsNumbnessState()) { useItemInformationPanel.GetComponentInChildren<Text>().text = toChara.GetCharacterName() + "は痺れ状態ではありません。"; } else { useItemInformationPanel.GetComponentInChildren<Text>().text = toChara.GetCharacterName() + "は痺れから回復しました。"; toChara.SetNumbness(false); // 持っているアイテム数を減らす fromChara.SetItemNum(item, fromChara.GetItemNum(item) - 1); } } // アイテムを使用したらアイテムを使用する相手のUseItemSelectCharacterPanelの子要素のボタンを全削除 for (int i = useItemSelectCharacterPanel.transform.childCount - 1; i >= 0; i--) { Destroy(useItemSelectCharacterPanel.transform.GetChild(i).gameObject); } // itemPanleButtonListから該当するアイテムを探し数を更新する var itemButton = itemPanelButtonList.Find(obj => obj.transform.Find("ItemName").GetComponent<Text>().text == item.GetKanjiName()); itemButton.transform.Find("Num").GetComponent<Text>().text = fromChara.GetItemNum(item).ToString(); // アイテム数が0だったらボタンとキャラクターステータスからアイテムを削除 if (fromChara.GetItemNum(item) == 0) { // アイテムが0になったら一気にItemPanelに戻す為、UseItemPanel内とUseItemSelectCharacterPanel内でのオブジェクト登録を削除 selectedGameObjectStack.Pop(); selectedGameObjectStack.Pop(); // itemPanelButtonListからアイテムパネルボタンを削除 itemPanelButtonList.Remove(itemButton); // アイテムパネルボタン自身の削除 Destroy(itemButton); // アイテムを渡したキャラクター自身のItemDictionaryからそのアイテムを削除 fromChara.GetItemDictionary().Remove(item); // ItemPanelに戻る為、UseItemPanel内に作ったボタンを全削除 for (int i = useItemPanel.transform.childCount - 1; i >= 0; i--) { Destroy(useItemPanel.transform.GetChild(i).gameObject); } // アイテム数が0になったのでCommandMode.NoItemPassedに変更 currentCommand = CommandMode.NoItemPassed; useItemInformationPanel.transform.SetAsLastSibling(); Input.ResetInputAxes(); } else { // アイテム数が残っている場合はUseItemPanelでアイテムをどうするかの選択に戻る currentCommand = CommandMode.UseItemSelectCharacterPanelToUseItemPanel; useItemInformationPanel.transform.SetAsLastSibling(); Input.ResetInputAxes(); } } |
使うアイテムの種類に応じて処理を分けています。
例えば使ったアイテムが回復アイテムならば相手のキャラクターのHPが最大かどうかを判断し、最大であれば使う必要がないのでその情報を表示し、少しでも体力が減っていれば回復し、アイテムを使ったキャラクターのアイテムのアイテム数を減らします。
状態回復の場合は相手のキャラクターの状態を見て、同じように状態異常でなければその情報を表示し、状態異常であれば回復し使ったキャラクターのアイテムのアイテム数を減らします。
アイテムを使用したらUseItemPanelに戻るのでUseItemSelectCharacterPanelの子要素に作ったキャラクター選択のボタン群は削除します。
このままだとItemPanelのアイテム一覧のアイテム数が減らないので、
1 2 3 4 5 | // itemPanleButtonListから該当するアイテムを探し数を更新する var itemButton = itemPanelButtonList.Find(obj => obj.transform.Find("ItemName").GetComponent<Text>().text == item.GetKanjiName()); itemButton.transform.Find("Num").GetComponent<Text>().text = fromChara.GetItemNum(item).ToString(); |
itemPanelButtonListにあらかじめ入れておいたItemPanelButton達の中からボタンの子要素のItemNameテキストの文字列と現在のアイテムの漢字名を比較して抽出し、そのボタンのNumテキストのアイテム数を更新しています。
上の場合ではアイテムパネルボタンのItemNameテキストに表示する名前が被っていない事を前提としています。
最後に使用したアイテムの数が0だったらUseItemPanelではなくItemPanelまで戻すのでその処理を行っています。
selectedGameObjectStackから不要となったボタンをポップし、itemPanelボタンに表示されているそのアイテムのボタンを削除します。
またキャラクターが持っているアイテムのItemDictionaryからそのアイテムを削除します。
ItemPanelに戻るのでUseItemPanelの子要素に作成したアイテムをどうするか?のボタン群を全て削除します。
使用したアイテムの数が残っている場合はUseItemPanelに戻り、そのアイテムをどうするか?の選択に戻ります。
アイテム数が残っている場合はcurrentCommandにCommandMode.UseItemSelectCharacterPanelToUseItemPanelを設定し、useItemInformationPanelにアイテムを使用した旨を表示します。
『アイテム使用後の情報を消し次の事を行う為の処理』の項目で説明されていますが、アイテムを使用、渡す、捨てる、装備する、装備を外す等をした時にuseItemInformationPanelにそれらの情報を表示し、一度何らかのキーやボタンが押されたら他のパネルに移動するようになっています(currentCommandは違う)。
PassItemメソッドの作成
次はアイテムを『渡す』のボタンを押した時に実行するPassItemメソッドを作成します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | // 渡す public void PassItem(AllyStatus allyStatus, Item item) { useItemPanelCanvasGroup.interactable = false; useItemSelectCharacterPanel.SetActive(true); // UseItemPanelでどれを最後に選択していたか selectedGameObjectStack.Push(EventSystem.current.currentSelectedGameObject); GameObject characterButtonIns; // パーティメンバー分のボタンを作成 foreach (var member in partyStatus.GetAllyStatus()) { if (member != allyStatus) { characterButtonIns = Instantiate<GameObject>(characterPanelButtonPrefab, useItemSelectCharacterPanel.transform); characterButtonIns.GetComponentInChildren<Text>().text = member.GetCharacterName(); characterButtonIns.GetComponent<Button>().onClick.AddListener(() => PassItemToOtherCharacter(allyStatus, member, item)); } } // UseItemSelectCharacterPanelに移行する currentCommand = CommandMode.UseItemSelectCharacterPanel; useItemSelectCharacterPanel.transform.SetAsLastSibling(); EventSystem.current.SetSelectedGameObject(useItemSelectCharacterPanel.transform.GetChild(0).gameObject); useItemSelectCharacterPanelCanvasGroup.interactable = true; Input.ResetInputAxes(); } |
PassItemメソッドはそのアイテムを誰に渡すか?をUseItemSelectCharacterPanelの子要素にボタンとして表示しますが、アイテムを渡す相手から自分自身を排除します(ユニティちゃんなら大鳥ゆうじにしか渡さない)。
作成したボタンを押した時に実行するメソッドはPassItemToOtherCharacterメソッドを設定します。
PassItemToOtherCharacterメソッドの作成
アイテムを『渡す』を選択した後に、UseItemSelectCharacterPanelの子要素のボタンを押して渡す相手のキャラクターを選択した時に実行するPassItemToOtherCharacterメソッドを作成します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | // 渡す相手を指定しアイテム数の増減をする public void PassItemToOtherCharacter(AllyStatus fromChara, AllyStatus toChara, Item item) { useItemInformationPanel.SetActive(true); useItemSelectCharacterPanelCanvasGroup.interactable = false; useItemSelectCharacterPanel.SetActive(false); // 持っているアイテム数を減らす fromChara.SetItemNum(item, fromChara.GetItemNum(item) - 1); // 渡されたキャラクターがアイテムを持っていなければそのアイテムを登録 if (!toChara.GetItemDictionary().ContainsKey(item)) { toChara.SetItemDictionary(item, 0); } // 渡されたキャラクターのアイテム数を増やす toChara.SetItemNum(item, toChara.GetItemNum(item) + 1); // アイテムを渡し終わったらアイテムを渡す相手のUseItemSelectCharacterPanelの子要素のボタンを全削除 for (int i = useItemSelectCharacterPanel.transform.childCount - 1; i >= 0; i--) { Destroy(useItemSelectCharacterPanel.transform.GetChild(i).gameObject); } // itemPanleButtonListから該当するアイテムを探し数を更新する var itemButton = itemPanelButtonList.Find(obj => obj.transform.Find("ItemName").GetComponent<Text>().text == item.GetKanjiName()); itemButton.transform.Find("Num").GetComponent<Text>().text = fromChara.GetItemNum(item).ToString(); // アイテムを渡した旨を表示 useItemInformationPanel.GetComponentInChildren<Text>().text = fromChara.GetCharacterName() + "は" + item.GetKanjiName() + "を" + toChara.GetCharacterName() + "に渡しました。"; // アイテム数が0だったらボタンとキャラクターステータスからアイテムを削除 if (fromChara.GetItemNum(item) == 0) { // 装備している武器や鎧だったら装備を外す if (fromChara.GetEquipArmor() == item) { fromChara.SetEquipArmor(null); } else if (fromChara.GetEquipWeapon() == item) { fromChara.SetEquipWeapon(null); } // アイテムが0になったら一気にItemPanelに戻す為、UseItemPanel内とUseItemSelectCharacterPanel内でのオブジェクト登録を削除 selectedGameObjectStack.Pop(); selectedGameObjectStack.Pop(); // itemPanelButtonListからアイテムパネルボタンを削除 itemPanelButtonList.Remove(itemButton); // アイテムパネルボタン自身の削除 Destroy(itemButton); // アイテムを渡したキャラクター自身のItemDictionaryからそのアイテムを削除 fromChara.GetItemDictionary().Remove(item); // ItemPanelに戻る為、UseItemPanel内に作ったボタンを全削除 for (int i = useItemPanel.transform.childCount - 1; i >= 0; i--) { Destroy(useItemPanel.transform.GetChild(i).gameObject); } // アイテム数が0になったのでCommandMode.NoItemPassedに変更 currentCommand = CommandMode.NoItemPassed; useItemInformationPanel.transform.SetAsLastSibling(); Input.ResetInputAxes(); } else { // アイテム数が残っている場合はUseItemPanelでアイテムをどうするかの選択に戻る currentCommand = CommandMode.UseItemSelectCharacterPanelToUseItemPanel; useItemInformationPanel.transform.SetAsLastSibling(); Input.ResetInputAxes(); } } |
渡したキャラクターのアイテム数を減らし、アイテムを渡す相手がそのアイテムを持っていなければそのキャラクターのItemDictionaryにそのアイテムを登録します。
その後に渡されたキャラクターのアイテム数を増やします。
アイテムを渡し終わった時もアイテムを使用した時と同じで、アイテム数が0であればItemPanel、アイテムが残っていればUseItemPanelに移動します。
アイテムが装備品で渡すキャラクターが1つしかそのアイテムを持っていない時は装備を外す必要があります。
やっていることはほとんど『使用』と同じなので問題はないと思います。
ThrowAwayItemメソッドの作成
アイテムを『捨てる』を選択した時に実行するThrowAwayItemメソッドを作成します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | // 捨てる public void ThrowAwayItem(AllyStatus allyStatus, Item item) { // アイテム数を減らす allyStatus.SetItemNum(item, allyStatus.GetItemNum(item) - 1); // アイテム数が0になった時 if (allyStatus.GetItemNum(item) == 0) { // 装備している武器を捨てる場合の処理 if (item == allyStatus.GetEquipArmor()) { var equipArmorButton = itemPanelButtonList.Find(itemPanelButton => itemPanelButton.transform.Find("ItemName").GetComponent<Text>().text == item.GetKanjiName()); equipArmorButton.transform.Find("Equip").GetComponent<Text>().text = ""; equipArmorButton = null; allyStatus.SetEquipArmor(null); } else if (item == allyStatus.GetEquipWeapon()) { var equipWeaponButton = itemPanelButtonList.Find(itemPanelButton => itemPanelButton.transform.Find("ItemName").GetComponent<Text>().text == item.GetKanjiName()); equipWeaponButton.transform.Find("Equip").GetComponent<Text>().text = ""; equipWeaponButton = null; allyStatus.SetEquipWeapon(null); } } // ItemPanelの子要素のアイテムパネルボタンから該当するアイテムのボタンを探して数を更新する var itemButton = itemPanelButtonList.Find(obj => obj.transform.Find("ItemName").GetComponent<Text>().text == item.GetKanjiName()); itemButton.transform.Find("Num").GetComponent<Text>().text = allyStatus.GetItemNum(item).ToString(); useItemInformationPanel.GetComponentInChildren<Text>().text = item.GetKanjiName() + "を捨てました。"; // アイテム数が0だったらボタンとキャラクターステータスからアイテムを削除 if (allyStatus.GetItemNum(item) == 0) { selectedGameObjectStack.Pop(); itemPanelButtonList.Remove(itemButton); Destroy(itemButton); allyStatus.GetItemDictionary().Remove(item); currentCommand = CommandMode.NoItemPassed; useItemPanelCanvasGroup.interactable = false; useItemPanel.SetActive(false); useItemInformationPanel.transform.SetAsLastSibling(); useItemInformationPanel.SetActive(true); // ItemPanelに戻る為UseItemPanelの子要素のボタンを全削除 for (int i = useItemPanel.transform.childCount - 1; i >= 0; i--) { Destroy(useItemPanel.transform.GetChild(i).gameObject); } } else { useItemPanelCanvasGroup.interactable = false; useItemInformationPanel.transform.SetAsLastSibling(); useItemInformationPanel.SetActive(true); currentCommand = CommandMode.UseItemPanelToUseItemPanel; } Input.ResetInputAxes(); } |
こちらもアイテム数を減らしたり、減らした後のアイテムの数を見て戻るパネルを選択しているだけで行っていることは『使用』『渡す』と同じです。
ただアイテムが0の時の処理の流れが『渡す』と変わってますね・・・・・(^_^;)
最初の方にアイテム数が0の時の処理をしてますが、最後の方でもアイテム数が0の時で判定しているのでそこに移してもいいかもしれません(『渡す』の方はそうしているかも)。
Equipメソッドの作成
アイテムを『装備する』ボタンを押した時に実行するEquipメソッドを作成していきます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 | // 装備する public void Equip(AllyStatus allyStatus, Item item) { // キャラクター毎に装備出来る武器や鎧かどうかを調べ装備を切り替える if (allyStatus.GetCharacterName() == "ユニティちゃん") { if (item.GetItemType() == Item.Type.ArmorAll || item.GetItemType() == Item.Type.ArmorUnityChan) { var equipArmorButton = itemPanelButtonList.Find(itemPanelButton => itemPanelButton.transform.Find("ItemName").GetComponent<Text>().text == item.GetKanjiName()); equipArmorButton.transform.Find("Equip").GetComponent<Text>().text = "E"; // 装備している鎧があればItemPanelでEquipのEを外す if (allyStatus.GetEquipArmor() != null) { equipArmorButton = itemPanelButtonList.Find(itemPanelButton => itemPanelButton.transform.Find("ItemName").GetComponent<Text>().text == allyStatus.GetEquipArmor().GetKanjiName()); equipArmorButton.transform.Find("Equip").GetComponent<Text>().text = ""; } allyStatus.SetEquipArmor(item); useItemInformationPanel.GetComponentInChildren<Text>().text = allyStatus.GetCharacterName() + "は" + item.GetKanjiName() + "を装備しました。"; } else if (item.GetItemType() == Item.Type.WeaponAll || item.GetItemType() == Item.Type.WeaponUnityChan) { var equipWeaponButton = itemPanelButtonList.Find(itemPanelButton => itemPanelButton.transform.Find("ItemName").GetComponent<Text>().text == item.GetKanjiName()); equipWeaponButton.transform.Find("Equip").GetComponent<Text>().text = "E"; // 装備している武器があればItemPanelでEquipのEを外す if (allyStatus.GetEquipWeapon() != null) { equipWeaponButton = itemPanelButtonList.Find(itemPanelButton => itemPanelButton.transform.Find("ItemName").GetComponent<Text>().text == allyStatus.GetEquipWeapon().GetKanjiName()); equipWeaponButton.transform.Find("Equip").GetComponent<Text>().text = ""; } allyStatus.SetEquipWeapon(item); useItemInformationPanel.GetComponentInChildren<Text>().text = allyStatus.GetCharacterName() + "は" + item.GetKanjiName() + "を装備しました。"; } else { useItemInformationPanel.GetComponentInChildren<Text>().text = allyStatus.GetCharacterName() + "は" + item.GetKanjiName() + "を装備出来ません。"; } } else if (allyStatus.GetCharacterName() == "大鳥ゆうじ") { if (item.GetItemType() == Item.Type.ArmorAll || item.GetItemType() == Item.Type.ArmorYuji) { var equipArmorButton = itemPanelButtonList.Find(itemPanelButton => itemPanelButton.transform.Find("ItemName").GetComponent<Text>().text == item.GetKanjiName()); equipArmorButton.transform.Find("Equip").GetComponent<Text>().text = "E"; if (allyStatus.GetEquipArmor() != null) { equipArmorButton = itemPanelButtonList.Find(itemPanelButton => itemPanelButton.transform.Find("ItemName").GetComponent<Text>().text == allyStatus.GetEquipArmor().GetKanjiName()); equipArmorButton.transform.Find("Equip").GetComponent<Text>().text = ""; } allyStatus.SetEquipArmor(item); useItemInformationPanel.GetComponentInChildren<Text>().text = allyStatus.GetCharacterName() + "は" + item.GetKanjiName() + "を装備しました。"; } else if (item.GetItemType() == Item.Type.WeaponAll || item.GetItemType() == Item.Type.WeaponYuji) { var equipWeaponButton = itemPanelButtonList.Find(itemPanelButton => itemPanelButton.transform.Find("ItemName").GetComponent<Text>().text == item.GetKanjiName()); equipWeaponButton.transform.Find("Equip").GetComponent<Text>().text = "E"; if (allyStatus.GetEquipWeapon() != null) { equipWeaponButton = itemPanelButtonList.Find(itemPanelButton => itemPanelButton.transform.Find("ItemName").GetComponent<Text>().text == allyStatus.GetEquipWeapon().GetKanjiName()); equipWeaponButton.transform.Find("Equip").GetComponent<Text>().text = ""; } allyStatus.SetEquipWeapon(item); useItemInformationPanel.GetComponentInChildren<Text>().text = allyStatus.GetCharacterName() + "は" + item.GetKanjiName() + "を装備しました。"; } else { useItemInformationPanel.GetComponentInChildren<Text>().text = allyStatus.GetCharacterName() + "は" + item.GetKanjiName() + "を装備出来ません。"; } } // 装備を切り替えたらItemPanelに戻る useItemPanelCanvasGroup.interactable = false; useItemPanel.SetActive(false); itemPanelCanvasGroup.interactable = true; // ItemPanelに戻るのでUseItemPanelの子要素に作ったボタンを全削除 for (int i = useItemPanel.transform.childCount - 1; i >= 0; i--) { Destroy(useItemPanel.transform.GetChild(i).gameObject); } useItemInformationPanel.transform.SetAsLastSibling(); useItemInformationPanel.SetActive(true); currentCommand = CommandMode.UseItemPanelToItemPanel; Input.ResetInputAxes(); } |
スクリプトが長くなっていますが、やっていることはそのキャラクターが装備できるものかどうかを判断し、装備出来ればItemPanelのアイテムパネルボタンの横に『E』を表示し、装備していた装備品の装備を外しているだけです。
縦にも横にもスクリプトが長いので難しそうな処理をしてそうですが、やっていることは今までと同じです。
RemoveEquipメソッドの作成
アイテムの『装備を外す』ボタンを押した時に実行するRemoveEquipメソッドを作成します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | // 装備を外す public void RemoveEquip(AllyStatus allyStatus, Item item) { // アイテムの種類に応じて装備を外す if (item.GetItemType() == Item.Type.ArmorAll || item.GetItemType() == Item.Type.ArmorUnityChan || item.GetItemType() == Item.Type.ArmorYuji) { var equipArmorButton = itemPanelButtonList.Find(itemPanelButton => itemPanelButton.transform.Find("ItemName").GetComponent<Text>().text == item.GetKanjiName()); equipArmorButton.transform.Find("Equip").GetComponent<Text>().text = ""; allyStatus.SetEquipArmor(null); } else if (item.GetItemType() == Item.Type.WeaponAll || item.GetItemType() == Item.Type.WeaponUnityChan || item.GetItemType() == Item.Type.WeaponYuji) { var equipArmorButton = itemPanelButtonList.Find(itemPanelButton => itemPanelButton.transform.Find("ItemName").GetComponent<Text>().text == item.GetKanjiName()); equipArmorButton.transform.Find("Equip").GetComponent<Text>().text = ""; allyStatus.SetEquipWeapon(null); } // 装備を外した旨を表示 useItemInformationPanel.GetComponentInChildren<Text>().text = allyStatus.GetCharacterName() + "は" + item.GetKanjiName() + "を外しました。"; // 装備を外したらItemPanelに戻る処理 useItemPanelCanvasGroup.interactable = false; useItemPanel.SetActive(false); itemPanelCanvasGroup.interactable = true; // ItemPanelに戻るのでUseItemPanelの子要素のボタンを全削除 for (int i = useItemPanel.transform.childCount - 1; i >= 0; i--) { Destroy(useItemPanel.transform.GetChild(i).gameObject); } useItemInformationPanel.transform.SetAsLastSibling(); useItemInformationPanel.SetActive(true); currentCommand = CommandMode.UseItemPanelToItemPanel; Input.ResetInputAxes(); } |
鎧か武器かで判断しキャラクターの装備から外します。
UIの外をマウスクリックした時の処理
今のままだとマウスのクリックでコマンドの選択をする時にボタン外をクリックするとボタンの選択が解除されてしまいます。
そこでEventSystemの選択が解除された時に現在のcurrentCommandに応じてそのパネルの一番最初の子要素を無理やり選択状態にし、選択が解除されている状態がないようにしておきます。
Updateメソッドの最後に以下の処理を追加します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | // 選択解除された時(マウスでUI外をクリックした)は現在のモードによって無理やり選択させる if (EventSystem.current.currentSelectedGameObject == null) { if (currentCommand == CommandMode.CommandPanel) { EventSystem.current.SetSelectedGameObject(commandPanel.transform.GetChild(0).gameObject); } else if (currentCommand == CommandMode.ItemPanel) { EventSystem.current.SetSelectedGameObject(content.transform.GetChild(0).gameObject); } else if (currentCommand == CommandMode.ItemPanelSelectCharacter) { EventSystem.current.SetSelectedGameObject(selectCharacterPanel.transform.GetChild(0).gameObject); } else if (currentCommand == CommandMode.StatusPanel) { EventSystem.current.SetSelectedGameObject(selectCharacterPanel.transform.GetChild(0).gameObject); } else if (currentCommand == CommandMode.StatusPanelSelectCharacter) { EventSystem.current.SetSelectedGameObject(selectCharacterPanel.transform.GetChild(0).gameObject); } else if (currentCommand == CommandMode.UseItemPanel) { EventSystem.current.SetSelectedGameObject(useItemPanel.transform.GetChild(0).gameObject); } else if (currentCommand == CommandMode.UseItemSelectCharacterPanel) { EventSystem.current.SetSelectedGameObject(useItemSelectCharacterPanel.transform.GetChild(0).gameObject); } } |
EventSystem.current.currentSelectedGameObjectがnullの時はUIが選択されていない状態なので、その時のcurrentCommandの状態を見て、該当するパネルの最初の子要素を無理やり選択させるようにしています。
これで機能が出来たのでCommandゲームオブジェクトのCommandScriptのItemPanelButtonPrefabにAssets/RPG/Prefabs/UI/Command/ItemPanelButtonプレハブを設定し、
UseItemPanelButtonPrefabにAssets/RPG/UI/Command/UseItemPanelButtonプレハブを設定します。
アイテム一覧にあらかじめボタンを配置しておく方法
この記事の最初の方で言及しましたが、この記事を含めてユニティちゃんのRPGを作ってみようのカテゴリ全般でUIのパネルに表示するボタンをプレハブからインスタンス化しています。
ですがこの方法だと今開いているパネルの前のパネルに戻った時にインスタンス化したボタンを全部削除する処理が必要になります。
なのでアイテム数が多くなったり頻繁にキャンセルボタンを押して戻って選択して戻ってという処理を繰り返すと無駄にボタンのゲームオブジェクトの削除と生成を繰り返します。
そこでアイテム一覧等にあらかじめボタンを配置しておいてあらかじめあるボタンを操作してボタンの子要素のTextやボタンを押した時の動作を設定した方がいいかもしれません。
わたくしの場合は最初にボタンプレハブをインスタンス化する方法で作ってしまったのでもう書き換えませんが・・・・(^_^;)
あらかじめボタンを配置しておくやり方を書いておきます。
キャラクター選択パネルなどでもあらかじめボタンを配置しておくことが出来ますが、個数が多いアイテム一覧を例にとっています。
まずはItemPanelの子要素のContentにAssets/RPG/Prefabs/UI/ItemPanelButtonプレハブをゲーム内で使用するアイテムの総数分作成します(持っているアイテムより少なく作ってはいけません)。
スクロール関連のスクリプト等は次の記事で作成します。
次にアイテム一覧で一回に表示されるアイテムボタンの最後の二つにScrollDownScriptを取り付け、次の画面の最初のアイテムボタンにScrollUpScriptを取り付けます。
次にCommandScriptのOnEnableメソッドでアイテムパネルボタンがあれば削除していた箇所をコメントにするか削除します(消す必要がなくなったからです)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | private void OnEnable() { // 現在のコマンドの初期化 currentCommand = CommandMode.CommandPanel; // コマンドメニュー表示時に他のパネルは非表示にする statusPanel.SetActive(false); selectCharacterPanel.SetActive(false); itemPanel.SetActive(false); useItemPanel.SetActive(false); useItemSelectCharacterPanel.SetActive(false); itemInformationPanel.SetActive(false); useItemInformationPanel.SetActive(false); // キャラクター選択ボタンがあれば全て削除 for (int i = selectCharacterPanel.transform.childCount - 1; i >= 0; i--) { Destroy(selectCharacterPanel.transform.GetChild(i).gameObject); } //// アイテムパネルボタンがあれば全て削除 //for (int i = content.transform.childCount - 1; i >= 0; i--) { // Destroy(content.transform.GetChild(i).gameObject); //} |
Updateメソッドのキャンセルボタンを押した時の処理でも同様にアイテムパネルボタンを削除している所をコメントにするか削除します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | private void Update() { // キャンセルボタンを押した時の処理 if (Input.GetButtonDown("Cancel")) { // コマンド選択画面時 if (currentCommand == CommandMode.CommandPanel) { // ステータスキャラクター選択またはステータス表示時 } else if (currentCommand == CommandMode.StatusPanelSelectCharacter || currentCommand == CommandMode.StatusPanel ) { // どのキャラクターのアイテムを表示するかの選択時 } else if (currentCommand == CommandMode.ItemPanelSelectCharacter) { // アイテム一覧表示時 } else if (currentCommand == CommandMode.ItemPanel) { itemPanelCanvasGroup.interactable = false; itemPanel.SetActive(false); itemInformationPanel.SetActive(false); // リストをクリア itemPanelButtonList.Clear(); //// ItemPanelでCancelを押したらcontent以下のアイテムパネルボタンを全削除 //for (int i = content.transform.childCount - 1; i >= 0; i--) { // Destroy(content.transform.GetChild(i).gameObject); //} |
キャラクターが持っているアイテムのボタンを表示しているCreateItemPanelButtonメソッドを修正します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 | // キャラクターが持っているアイテムのボタン表示 public void CreateItemPanelButton(AllyStatus allyStatus) { itemInformationPanel.SetActive(true); selectCharacterPanelCanvasGroup.interactable = false; // アイテムパネルボタンを何個作成したかどうか int itemPanelButtonNum = 0; GameObject itemButtonIns; // 選択したキャラクターのアイテム数分アイテムパネルボタンを作成 // 持っているアイテム分のボタンの作成とクリック時の実行メソッドの設定 foreach (var item in allyStatus.GetItemDictionary().Keys) { itemButtonIns = content.transform.GetChild(itemPanelButtonNum).gameObject; itemButtonIns.SetActive(true); itemButtonIns.transform.Find("ItemName").GetComponent<Text>().text = item.GetKanjiName(); itemButtonIns.GetComponent<Button>().onClick.RemoveAllListeners(); itemButtonIns.GetComponent<Button>().onClick.AddListener(() => SelectItem(allyStatus, item)); itemButtonIns.GetComponent<ItemPanelButtonScript>().SetParam(item); // アイテム数を表示 itemButtonIns.transform.Find("Num").GetComponent<Text>().text = allyStatus.GetItemNum(item).ToString(); // 装備している武器や防具には名前の前にEを表示し、そのTextを保持して置く if (allyStatus.GetEquipWeapon() == item) { itemButtonIns.transform.Find("Equip").GetComponent<Text>().text = "E"; } else if (allyStatus.GetEquipArmor() == item) { itemButtonIns.transform.Find("Equip").GetComponent<Text>().text = "E"; } // アイテムパネルボタン番号を更新 itemPanelButtonNum++; } for (int i = itemPanelButtonNum; i < content.transform.childCount; i++) { content.transform.GetChild(i).gameObject.SetActive(false); } // アイテムパネルの表示と最初のアイテムの選択 if (itemPanelButtonNum != 0) { // SelectCharacerPanelで最後にどのゲームオブジェクトを選択していたか selectedGameObjectStack.Push(EventSystem.current.currentSelectedGameObject); currentCommand = CommandMode.ItemPanel; itemPanel.SetActive(true); itemPanel.transform.SetAsLastSibling(); itemPanelCanvasGroup.interactable = true; EventSystem.current.SetSelectedGameObject(content.transform.GetChild(0).gameObject); } else { informationTitleText.text = ""; informationText.text = "アイテムを持っていません。"; selectCharacterPanelCanvasGroup.interactable = true; } } |
ItemPanelButtonPrefabをインスタンス化していた箇所を
1 2 3 | content.transform.GetChild(itemPanelButtonNum).gameObject |
としてcontentの子要素のゲームオブジェクトを順番に取得するようにします。
以前アイテム一覧を開いた時に持っているアイテムの数より後のボタンは非表示にしている可能性がある為、アクティブにしておきます。
1 2 3 | itemButtonIns.SetActive(true); |
ボタンには依然開いた時にボタンを押した時に実行するメソッドが設定されている可能性があるので
1 2 3 | itemButtonIns.GetComponent<Button>().onClick.RemoveAllListeners(); |
でボタンを押した時に実行する処理を削除します。
あらためてボタンが押された時にSelectItemメソッドの呼び出し処理の追加と引数を設定します。
アイテムのボタンはインスタンス化するか元から配置しているものを使うかの違いだけなので大きな変化はありません。
ただItemPanelButtonは持っているアイテム数以上に配置したのでアイテム数を超えた場合はその後のアイテムボタンは非表示にします。
アイテムを一個も持っていない時のif文の条件は
1 2 3 | if (itemPanelButtonNum != 0) { |
という条件に変更します。
これであらかじめItemPanelButtonを配置しても同じような処理に出来ました。
アイテムコマンドの確認
これで機能が出来ました。
実行して試してみましょう。
上のようにアイテムコマンドが出来上がりました。
終わりに
今回のアイテムコマンドの処理は非常に面倒な処理が多いですね・・・・。
処理も分かり辛くなってますし・・・・、量が多いのでどこか記述漏れや間違いがあるかもしれません。(._.)
前回のステータスコマンドと今回のアイテムコマンドはパネルを開いてそのパネルを最前面に表示しコマンド処理をしていますが、Animationを使ってUI画面が動くように作るとまた違った良さが出そうですね。
この作品はユニティちゃんライセンス条項の元に提供されています