i-school - 2DタイルマップRPG 手順18
 引き続きまして、アイテムの管理方法について実装を行います。

 ベースとしましては、かめくめ様のこちらの記事を参考にさせていただいております。
ありがとうございます<(_ _)>

Unityを使った3Dゲームの作り方(かめくめ)
Unityでキーやゲームパッドで操作するステータス画面の作成
https://gametukurikata.com/ui/statuswindow


 上記の実装と前回の手順の実装を行った上で、こちらの処理を追加で実装を行います。


手順18 −アイテムの管理方法の準備−
31.ItemButton プレファブを元に ItemButtonDetail ゲームオブジェクトを作成してプレファブにする
32.ItemButtonDetail スクリプトを作成する


 新しい学習内容は、以下の通りです。

 ・プレファブの解除(アンパック)方法
 ・ItemData クラスの情報を参照する方法
 ・Behaviour.enabled 変数
 ・Selectable.interactable 変数



 今回の実装は3つの手順に沿って実装を行います。そのため、まずは全体の流れを把握し、それを順番に作成していきます。

〇1.アイテムインベントリーに表示するアイテム1つ1つの情報を ItemData クラスとして作成し、それを ItemDataSO スクリプタブル・オブジェクトを作成して管理を行うための準備をする
〇2.アイテムインベントリー内に表示する個別のアイテムのボタン、およびデータ情報を表示するための ItemButtonDetail ゲームオブジェクトと、それらの情報を制御するための ItemButtonDetail スクリプトを作成する
 3.GameData スクリプトと DataBaseManager スクリプトを修正して、ItemDataSO スクリプタブル・オブジェクトに登録したアイテムの情報を運用する処理を実装する
 4.アイテムインベントリー内に表示する ItemButtonDetail ゲームオブジェクトを所持している数に合わせて生成を行う ItemButtonManager スクリプトを作成する

 今回の手順では、〇2を実装します。



31.ItemButton プレファブを元に ItemButtonDetail ゲームオブジェクトを作成してプレファブにする

1.設計


 アイテムインベントリーに作成するアイテムの情報を「アイテムを1つ以上所有している」という条件へと変更し、
インベントリー内に作成されるゲームオブジェクトの内容に「所有数」を追加します。

 現在はプレファブ化してある ItemButton ゲームオブジェクトをインスタンスしてインベントリー内にアイテムの情報を1つずつ作成していますので、
こちらのゲームオブジェクトを元に、別のゲームオブジェクトを利用する方法に変更します。


2.ItemButton プレファブを元に ItemButtonDetail ゲームオブジェクトを作成し、利用しないコンポーネントを削除する


 プレファブ状態の ItemButton ゲームオブジェクトをドラッグアンドドロップしてヒエラルキーに設置します。


ヒエラルキー画像



 ItemButton ゲームオブジェクトの上で右クリックをしてメニューを開き、Prefab => Unpack Completely を選択して、プレファブ状態を解除します。

 続いて名前を ItemButtonDetail に変更します。


ヒエラルキー画像




 最後に、利用しなくなったコンポーネントを削除します。


 ItemButtonDetail ゲームオブジェクトにアタッチされている Image コンポーネントと Canvas Renderer コンポーネントを Remove します
また、btnItem ゲームオブジェクトにアタッチされている ItemButton コンポーネントを Remove します


ItemButtonDetail ゲームオブジェクト インスペクター画像



btnItem ゲームオブジェクト インスペクター画像



 以上で設定は完了です。次にゲーム内に情報を表示するために必要なゲームオブジェクトを追加していきます。


3.ItemButtonDetail ゲームオブジェクトにゲームオブジェクトを追加する


 画面に表示したい情報に合わせて、その情報を扱うためのコンポーネントと、そのコンポーネントがアタッチされたゲームオブジェクトを追加していきます。

 基本的には次のような情報を表示させることになりますので、それに合わせてゲームオブジェクトを追加していきます。

<ItemButtonDetail ゲームオブジェクトで扱う情報群>
 1.アイテムの名前の表示場所 => Text コンポーネントがアタッチされたゲームオブジェクト txtItemName として作成する
 2.アイテムの情報の表示場所 => Text コンポーネントがアタッチされたゲームオブジェクト txtItemInfo として作成する
 3.アイテムの所有数の表示場所 => Textコンポーネントがアタッチされたゲームオブジェクト txtItemCount として作成する

<以下はすでにあるもの>
 4.ボタン機能        => Button コンポーネントと Image コンポーネントがアタッチされたゲームオブジェクト btnItem 
 5.アイテムの画像の表示場所 => Image コンポーネントがアタッチされたゲームオブジェクト btnItem 

 作成したゲームオブジェクトの大きさなどは任意です。このゲームオブジェクトがアイテムインベントリー内に並ぶことになりますので、
それを考えて各ゲームオブジェクトの設定を行ってみてください。

 参考画像を掲載しますが、この通りに作成する必要はありません。


4.必要なゲームオブジェクトを作成する


 上記の手順を元に3つのゲームオブジェクトを作成してください。
いずれも Text コンポーネントを持つゲームオブジェクトですので、それをふまえて作成をおこなってください。


txtItemName ゲームオブジェクト Sceneビュー画像




txtItemInfo ゲームオブジェクト Sceneビュー画像




txtItemCount ゲームオブジェクト Sceneビュー画像



 以上でゲームオブジェクトを用意ができました。

 最後に、ItemButtonDetail ゲームオブジェクトをプレファブにしてください。
プレファブ後はヒエラルキーにある ItemButtonDetail ゲームオブジェクトは削除してください。


プレファブ後の ItemButtonDetail ゲームオブジェクト



32.ItemButtonDetail スクリプトを作成する

1.設計


 いままでのアイテムインベントリーでは、Item ゲームオブジェクトに ItemButton スクリプトがアタッチされ、そのスクリプトが Item ゲームオブジェクトの制御を行っていました。
それが生成されて情報を与えられることにより、インベントリー内にアイテムのボタンを形作っていました。

 今回も同じ手法で、ItemButtonDetail ゲームオブジェクトに対して、専用のスクリプトを作成して、それをアタッチし、
そのスクリプトを通じて、ItemButtonDetail ゲームオブジェクト内にあるゲームオブジェクトやコンポーネントを操作制御を行います。
アイテムの名前に加えて、所有しているアイテムの数を表示させたりするようにします。それをインベントリー内に複数生成して、インベントリーを構成します。


2.ItemButtonDetail スクリプトを作成する


 ItemButton スクリプトをベースにしていますので、今回追加したゲームオブジェクトに対して、
制御したいコンポーネントを考えて処理を組み立ててみてください。

 宣言する変数については操作・制御を行いたいコンポーネントを指定して用意を行います。

 メソッドについては OnDeselected メソッドはそのまま利用していただけますが、
他のものは手を加えたり、新しく作成を行う必要があります。

 まず前提として、ItemButtonDetail ゲームオブジェクトはプレファブになっており、
このプレファブは外部のスクリプトによって生成されることになります。
その際に、ItemData クラスの情報と所持している数の情報が定義されますので、その情報を引数を通じて受け取って、
ItemButtonDetail ゲームオブジェクトの各コンポーネントに設定を行う処理が必要になります。



 ItemData クラスの情報は、ItemData クラスの代入されている変数にピリオドを追加することで、内部の値の参照が可能になります。

    [SerializeField]
    private ItemDataSO.ItemData itemData;

    // 変数を使って、ItemData クラスの内部情報を参照
    itemData.itemName;



 処理の全体の流れを把握した上でスクリプトの処理を考えていくと分かりやすくなります。


ItemButtonDetail.cs

<= クリックすると開きます


 スクリプトを作成したらセーブを行います。


3.<Behaviour.enabled 変数>


 指定した型のオン・オフを切り替える変数です。
インスペクターのコンポーネント名の左側にあるスイッチを切り替えることで、コンポーネントのオン・オフを切り替えることが出来ます。
この処理をスクリプトから実行するための変数です。

 今回は Image コンポーネントの操作を行っていますが、Image に限らず、コライダーや レンダラーなど、ゲームオブジェクトにアタッチされているコンポーネントであれば、
すべてこの命令でオン・オフを切り替えることが出来ます。
true がチェックオン、false がチェックオフの状態に切り替わります。

 今回のケースでは、メソッドの引数である bool 型の isSwitch 変数に true か false の情報が届きますので、その値を利用して制御を行っています。

  imgItem.enabled = isSwitch;        

<検証動画 ゲーム中でスイッチがオフになる制御>
動画ファイルへのリンク

 
 上記の動画のように、この情報はインスペクター上で確認を行うことが可能ですので、制御処理を実装した場合には
対象となっているコンポーネントのスイッチのオン・オフの切り替えが行われているかを確認することが大切です。
どの情報が制御されているのかわからないと、修正を行うこともままならないからです。


参考サイト
Unity公式スクリプトリファレンス
Behaviour-enabled
https://docs.unity3d.com/ja/2018.4/ScriptReference...
Quita @OKsaiyowa 様
【Unity(C#)】コンポーネントのON・OFF(enable)とゲームオブジェクトの表示・非表示の切り替え(SetActive)
https://qiita.com/OKsaiyowa/items/9579ac348ac860cd...


4.<Selectable.interactable 変数>


 Button コンポーネントは、bool 型の interactable プロパティを持って(管理して)います。

 こちらのスイッチがオン(true)の場合、ボタンは有効な状態です。これを活性状態といいます。

 こちらのスイッチがオフ(false)の場合、ボタンは無効な状態です。
ボタンの色が Disabled Color で設定されている色に変わります(デフォルトは半透明な灰色)。これを非活性状態といいます。

 この情報はプロパティですので、スクリプトから操作をすることが出来ます。
今回はこちらの機能を利用してボタンを制御しつつ、視覚的にもわかるようにしています。

 実際にインスペクターで操作をしてみて、どのように変化するかを確認しておきましょう。

<ボタンを押せない状態にする処理>
  // ボタンを非活性化(半透明で押せない状態)
  btnItem.interactable = false;

<ボタンを押せる状態にする処理>
  // ボタンを非活性化(半透明で押せない状態)
  btnItem.interactable = true;

 今回はこの活性化/非活性化の切り替え処理をメソッドの引数を利用して1つの処理で運用出来るようにしています。
このような設計にしておくことで、false 用、true 用といった処理を分けて記述する必要がなくなるためです。
引数の活用方法を覚えると設計が楽になるだけではなく、面白くなります。

    /// <summary>
    /// ボタンのアクティブ状態の切り替え
    /// </summary>
    /// <param name="isSwitch"></param>
    public void SwithcActivateItemButtonDetail(bool isSwitch) {
        imgItem.enabled = isSwitch;
        btnItem.interactable = isSwitch;
    }

 この情報もインスペクター上で確認を行うことで出来ます。正常に制御が行われているかを確認しておいてください。


参考サイト
Unity公式スクリプティングAPI
Selectable.interactable
https://docs.unity3d.com/2019.1/Documentation/Scri...
すくまりのメモ帳 様
【Unity】Buttonをinteractableで無効化したり、動的にイベントを追加する方法
https://squmarigames.com/2018/12/10/unity-beginner...


5.ItemButtonDetail ゲームオブジェクトに ItemButtonDetail スクリプトをアタッチして設定を行う


 Assets 内にある、プレファブにした ItemButtonDetail ゲームオブジェクトを選択してインスペクターより Open Prefab を選択して、プレファブ編集モードに切り替えます。

 作成した ItemButtonDetail スクリプトを ItemButtonDetail ゲームオブジェクトにドラッグアンドドロップしてアタッチしてください。
アタッチしたら必ずインスペクターを確認します。


インスペクター画像





 SerializeField属性 で宣言している情報がインスペクター上に表示されていますので、こちらに制御を行うために必要な情報を登録します。
ずべてプレファブ内の情報ですので、必要なコンポーネントがアタッチされたゲームオブジェクトをドラッグアンドドロップしてアサインしてください。


アサイン後のインスペクター画像



 ItemData 内の各情報にはゲーム内でデータを設定しますので、この時点では何も情報を登録しないでおいてください


 最後に、EventTrigger の設定を行います。


6.btnItem ゲームオブジェクトにアタッチされている EventTrigger コンポーネントの設定を行う


 こちらに登録されている情報は ItemButton スクリプトの情報になりますので、ItemButtonDetail スクリプトの情報を再度登録し直します。
どの情報を登録すればいいのかわからない場合には、下記の画像を参考にしてください。


インスペクター画像



 EventTrigger についても色々なサイトに記事がありますので、是非調べて、自分の知識として吸収をしておいてください。

参考サイト
TECH Pjin 様
【Unity】Event Triggerの種類と用途と使い方【保存版】
https://tech.pjin.jp/blog/2017/09/03/unity_event-t...


 以上でこの手順は終了です。

 次は 手順19 −アイテムの管理方法の運用− です。