Unityでキャラクターの持ち物画面を作成する

今回はUnityで持ち物の画面を作成したいと思います。
ゲーム中にPauseモードでPauseUIを表示する代わりにステータス画面や持ち物画面を表示します。

今回は持ち物画面を表示するようにします。
全部の持ち物分のスロット(入れ物)を用意して、持っているアイテムは種類を表すアイコンをスロットに表示します。
スロットをクリックしたら情報欄にそのアイテムの情報を表示します。

今回作成する持ち物画面はマウス操作で実行しますので、ゲームパッドやキー操作出来る持ち物画面を作りたい方は

Unityでマウス、キーボードやゲームパッドで操作するステータス画面の作成をしていきます。

を参照してください。

スポンサーリンク

持ち物画面UIを作成

まずはPropertyUIという名前でUIを作成していきます。

プロパティ1

CanvasをPropertyUIという名前に変更し、子要素にPanel、その子要素にPanelを3つ作成し、Title、Main、Informationと作成します。
Informationには子要素にUIのTextを作成します。

プロパティ2

上のようにTitle、Main、Information(色ごとに分けてあります)という順になるように作成します。
名前やレイアウトは自由に変更してください。

プロパティ3

Mainのインスペクタを表示し、Add ComponentからLayout→Grid Layoutを選択します。
Cell Sizeで横幅と縦幅を指定します。Spacingでセル間の距離を指定します。

Start Cornerはどこから最初のセルを表示するか
Start Axisは縦と横のどちらにセルを並べていくか
Child Alignmentは子要素の並び位置
Constraintsは行と列の数に制限を持たせる

という設定になります。

今回は上の画像のように設定しました。

アイテムクラスItemDataとアイテム情報管理スクリプトItemDataBaseを作成

次にアイテムの情報を管理する為に、ItemDataクラススクリプトとアイテムの情報を保存しておくItemDataBaseスクリプトを作成します。

ItemDataというスクリプトを作成します。

アイテム情報にはアイテムの種類を表すアイコン、アイテムの名前、アイテムのタイプ、アイテムの情報を保存出来るようにします。

それぞれのデータを取得できるようにゲッターメソッドを用意します。

これでアイテムクラスの作成は終了です。

次にItemDataBaseスクリプトでアイテムを作成します。

ItemDataBaseはゲームに登場するアイテムの情報をすべて保持しておく為のクラスにします。

Awakeメソッドで全てのアイテム情報を設定しています。

Resources.LoadはAssetsフォルダのResourcesフォルダの中身を取得する時に使います。

あらかじめResourcesフォルダにインスタンス化したいプレハブ等を入れておくと利用したい時便利です。

第1引数が名前、第2引数が型です。

ItemDataの第2引数はアイテム名、第3引数はアイテムのタイプ、第4引数はアイテムの情報なのでそれぞれのアイテムの情報を書き込みます。

これでItemDataBaseスクリプトの完成です。

シーン全体を管理するスクリプトにItemDataBaseをAdd Componentで設定しておきます。

持ち物スロット(持ち物アイコンを入れる入れ物)の作成

次に持ち物を入れるスロットの作成をします。

プロパティ4

Mainの子要素にUI→Panelでパネルを作成し、その子要素にUI→Imageを作成します。
パネルの名前をPropertySlotと変更します。

パネルの大きさはPropertyUIの子要素のMainで設定したGrid Layoutのセルサイズで指定されるので、特別サイズの変更は必要ありません。

作成したPropertySlotはAssetsフォルダにドラッグ&ドロップしてプレハブにし、ヒエラルキー上のPropertySlotは削除します。

持ち物スロットをマウス操作した時の処理スクリプトProcessingSlotを作成

スロットのマウス操作処理関連スクリプトを作成しましょう。

名前はProcessingSlotとし、プレハブのPropertyUIに取り付けます。

ProcessingSlotはアイテムのスロットに設定し、それぞれのスロットで自身のアイテムデータを保持します。

OnDisableはゲームオブジェクトが非アクティブになった時に呼ばれるので、その時にタイトルUIが存在していればそれを削除し、自身のゲームオブジェクトを削除します。

SetItemDataはこのアイテムスロットを作成した時にそのアイテムのデータを引数として渡し呼び出します。

Startメソッドではアイテム情報を表示するInformationの子要素のTextを取得しています。

MouseOverはアイテムスロットの上にマウスポインタが入った時に呼び出すメソッドで、アイテムの名前を表示するTitleUIをインスタンス化します(TitleUIはこの後作ります)。

TitleUIの位置はスロットのサイズから調整した位置にインスタンス化しています。

タイトルUIはPropertyUIの子要素のPanelに設定し、サイズ調整はプレハブで出来るようにします。

タイトルUIのテキストには自身のアイテムデータの名前を設定し、Informationのテキストに自身のアイテムの情報を表示します。

MouseExitはマウスポインタがアイテムスロットから出た時の処理で、インスタンス化したTitleUIゲームオブジェクトを削除しています。

これでスロットに関する処理のスクリプトが出来ました。

TitleUIの作成

次はこの処理で使っているTitleUIの作成をします。

PropertyUI→Panelの子要素にUI→Panelを作成し名前をTitleUIとし、その子要素にUI→Textを作成します。

アイテム名表示UIの階層

TitleUIのパネルのサイズは、

アイテム表示UIのパネルのサイズ

↑のように設定します。

その子要素のTextは、

アイテム表示UIのテキストの設定

↑のように親のパネルのサイズに合わせて変化させるようにします。

TitleUIもTextもRaycast Targetのチェックを外し、マウスポインタが重なってもイベントを無視するようにします。

TitleUIをAssetsフォルダにドラッグ&ドロップしプレハブ化します。

プレハブ化したら、さきほどのProcessingSlotスクリプトインスペクタのtitleUIのところにTitleUIのプレハブをドラッグ&ドロップします。

プレハブにしたらヒエラルキー上のTitleUIは削除します。

PropertyUIのプレハブを選択し、インスペクタのAdd ComponentからEvent→Event Triggerを取り付けます。

アイテムスロットのイベントトリガーを設定

Event TriggerにはPointer EnterとPointer Exitイベントを取り付け、自身のゲームオブジェクト(PropertyUIプレハブ)を設定し取り付けてあるProcessingSlotスクリプトのMouseOverメソッドとMouserExitメソッドを設定します。

イベントトリガーに関しては

UnityのUIのクリックやドラッグのイベントを受け取る方法を勉強していきます。

を参考にしてください。

これでアイテムスロットの上にマウスが入った時と出て行った時の処理が完成しました。

アイテム数分のスロットを表示するCreateSlotScriptスクリプトを作成する

アイテムの総数分だけスロットを表示し、主人公が持っているアイテムだけスロットを表示するスクリプトを作成します。

名前はCreateSlotScriptとします。

スクリプトはPropertyUI→Panel→Mainに設定します。

OnEnableメソッドはこのスクリプトを設定しているMainゲームオブジェクトがアクティブになった時に呼ばれるので、その時にCreateSlotメソッドを呼び出します。

CreateSlotメソッドでは受け取ったItemDataの分だけスロットを作成しますが、そのアイテムを持っていなければスロットは作成しません。

その為に、MyItemStatus(持っているアイテム管理スクリプト)のGetItemFlagメソッドにアイテムのタイプを渡し、そのアイテムを持っているかを調べます。

持っていたらアイテムスロットプレハブをインスタンス化し、親をMainにします。

その後インスタンス化したアイテムスロットのlocalScaleを全て1に設定します(これをしないと0で初期化され表示されない為)。

最後にインスタンス化したアイテムスロットに設定しているProcessingSlotスクリプトを取得しSetItemDataメソッドを呼び出してアイテム情報をスロットで保持するようにします。

ちなみにMyItemStatusスクリプトは

↑のような感じで作成しています。

さて、これで持ち物画面の作成が完了しました。

持ち物画面を呼び出す処理の追加

後はゲームを中断した時に持ち物画面を呼び出し、ゲームを再開した時に消す処理を追加するだけです。
ゲームを中断する方法は

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

を参考にしてください。

持ち物画面は最初は表示したくないのでPropertyUIゲームオブジェクトは非アクティブにしておきます。

PropertyUIは最初非アクティブにしておく

↑のようにPropertyUIを非アクティブにしておかないとエラーが発生します。

空のゲームオブジェクトを作成し、名前をManagementとし、ItemDataBaseスクリプトを取り付けておきます。

Managementゲームオブジェクトを作成しItemDataBaseスクリプトを取り付ける

これで持ち物画面の作成と呼び出しが出来るようになりました。

回復アイテムを使いたい場合はクリック操作で処理をするという風にするといいかもしれません。

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

プロパティ8

上の画像は動作の一部になります。

画像が少し乱れていますが・・・・。

持ち物画面を作り終えて

とりあえず、これで持ち物画面の作成は終了です。

最初の記事からだいぶ処理を変更しました(2018/01/03)。

以前はだいぶ面倒くさい処理をしてましたが、少しだけスッキリ出来たような気もします。

またいつかこの記事を見た時に修正したくなるかもしれませんが・・・・(^_^;)

スポンサーリンク

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

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

コメント

  1. 匿名 より:

    ItemDataのスクリプトでobjectを継承していますが
    これだと16行目からのコンストラクタが使えなかったので
    修正したほうがいいと思います。

    • 確認してみたところ、わたくしの環境ではItemDataBaseからItemDataクラスのインスタンス化は出来ているようです。

      どういった内容のエラーが出ていますか?

      色々書き替えているので、元のスクリプトと変わってしまっているのかもしれません・・・(^_^;)

      • 匿名 より:

        おそらくかめさんはmonobehaviourを継承するとコンストラクタが
        無効になることを知っていてobjectを使ったのだと思います(?)
        エラーはでませんがItemDataには何も入りませんでした。(null状態)

        • ItemDataBaseのItemDataの中身は、PropertyUIをアクティブな状態でスタートさせていると中身が作成される前にCreateSlotScriptのCreateSlotメソッドが実行されエラーになります。

          CreateSlotScriptのOnEnableメソッドがItemDataBaseのAwakeメソッドで行っているItemDataクラスの作成より前に実行されてしまう為です。

          Unityマニュアルのイベント順ではAwake→OnEnableとなっていますが、それぞれ別のゲームオブジェクトでそれぞれのメソッドを作成しているとOnEnableが先に実行され、その後Awakeが実行されることがあるみたいです。

          この記事の仕様ではItemDataBaseクラスで個々のItemDataを作成するようにしている為、先にItemDataBaseクラスのAwakeが実行されるようPropertyUIを非アクティブにしています。

          その為、スロットを作成するタイミングをOnEnableで行わず、PropertyUIをオン・オフしているスクリプトで実行するとPropertyUIをアクティブな状態でスタートさせてもアイテムは表示されませんがエラーが出なくなります。

          いろいろ面倒になっていますが・・・・(^_^;)

          実行順序でItemDataクラスが作成されていないわけじゃない場合は、わたくしにはちょっとわかりません・・・・。

          ScriptableObjectを使ってあらかじめアイテムのデータを作成しておいてそれを利用したり、アイテムスロットはインスタンス化で作成せず最初から置いておいたほうが良いかもしれませんね。

          https://gametukurikata.com/basic/scriptableobject

  2. 絶対匿名希望さん より:

    TitleUIの作成のところで
    プレハブ化したら、さきほどのProcessSlotのtitleUIのところにTitleUIのプレハブをドラッグ&ドロップします。
    とありますが名前間違えてませんか?

  3. 匿名 より:

    すいません、RPGとかによくある「クエスト」機能なども作って頂けないでしょうか?
    どのクエストを受けたのか、だとか達成したのか、だとか。
    お願いします。