【Unity】RPGを作るチュートリアルその69 メニュー画面のアイテム機能の動作を実装
- 2025.04.23
- RPGチュートリアル
- RPG, Unity, ゲーム開発, チュートリアル

シンプルなRPGをUnityで作るチュートリアルシリーズの69回目です。
第68回ではメニュー画面のアイテム機能について動作を実装する準備として、マップ上で表示するメッセージウィンドウの機能を実装しました。
今回はメニュー画面のアイテム機能について動作を実装していきます。
制作環境
MacBook Pro 2023 Apple M2 Max
Unity6 (6000.0.30f1) Silicon
作業内容と順序
シンプルなRPGを作る上でどんな作業が必要か、どんな順番で作っていくと良さそうか、別ページで検討しました。基本的にこの流れに沿って進めていきます。
チュートリアルの一覧
このシリーズ全体の一覧は以下のページにまとめています。
前回の内容
前回はメニュー画面のアイテム機能について動作を実装する準備として、マップ上で表示するメッセージウィンドウの機能を実装しました。
メニュー画面の実装方針

メニュー画面では、
- アイテムの使用 ◀︎いまここ
- 魔法の使用
- 装備の選択
- ステータスの確認
- セーブ
- ゲームの終了
- メニューを閉じる
の項目を作成します。今回はこのうち、アイテム使用の機能について実装していきます。
アイテム画面の動作の実装
アイテム画面の動作を実装するにあたっては、
- アイテム画面のUIを制御するクラス
- アイテム画面のウィンドウ自体を制御するクラス
- ウィンドウ内でアイテムに関する処理を制御するクラス
- アイテムの使用処理を行うクラス
を作成したいと思います。
アイテムの各項目を制御するクラスについては、戦闘画面で作成した「SelectionItemController」がそのまま使えるので、これをアタッチします。以前のUI作成時に外しちゃいましたが、外さなくてもよかったかも……(1敗)
アイテム画面のウィンドウ自体を制御するクラス、ウィンドウ内でアイテムに関する処理を制御するクラスについては、戦闘画面の選択ウィンドウと同じ方式で実装します。魔法の機能を実装する際には、その担当部分を実装していきます。
アイテムの使用処理については、ウィンドウ制御のクラスとは別に作成していきます。
また、既存の「MenuManager」やトップ画面のクラスとも繋ぎ合わせて動作するようにしていきます。
アイテム画面のUIを制御するクラス
アイテム画面のUIを制御するクラスを作成します。基本的には戦闘画面で作成した選択ウィンドウのUIを制御するクラスを踏襲していきます。戦闘画面では項目が左上、右上、左下、右下、といった感じで順番を定義しましたが、メニュー画面では縦に並んでいて直感的に把握しやすいことからリスト形式で参照用のフィールドを用意します。
また、ページ数を表示するテキストもあるため、こちらの制御も行います。アイテムの説明に関しても親オブジェクトを分けてありますが、このクラスで制御するようにしたいと思います。
Projectウィンドウの「Assets/Scripts/Menu」のフォルダに移動し、MonoBehaviourのスクリプトファイルを作成します。名前は [MenuItemUIController] にしました。

作成した「MenuItemUIController」の中身は以下のように記載しました。
基本的な方針としては戦闘画面の選択ウィンドウと同様です。「_itemControllers」のフィールドでは各項目のコントローラをアサインします。上から0, 1, 2, …といったようにインデックスでアクセスできるようになっています。
ほとんど選択ウィンドウと共通していますが、この画面ではページ数を表示するテキストがあるので、SetPagerText()のメソッドを使ってセットできるようにしています。
アイテム画面のウィンドウ自体を制御するクラス
アイテム画面のウィンドウ自体を制御するクラスも作成します。こちらも同様に、戦闘画面の選択ウィンドウをベースにして実装していきましょう。ページ送りの方法が左右の矢印キー、上下の矢印キーはカーソル移動だけになるので、戦闘画面よりは計算は楽になるかもしれません。
また、UI、カーソルの移動やページ送りなど、戦闘画面と同様にアイテムと魔法で共通して使えるので、アイテム画面のウィンドウ自体を制御するクラスに加えて、アイテムに関して制御するクラス、魔法に関して制御するクラスを作成します。魔法に関しては魔法の機能を作る回で実装するので、今回はアイテムに関する部分を作成していきます。
Projectウィンドウの「Assets/Scripts/Menu」のフォルダにて、MonoBehaviourのスクリプトファイルを作成します。名前は [MenuItemWindowController] にしました。

それぞれ中身を記載していきます。
作成した「MenuItemWindowController」の中身は以下のように記載しました。(ちょっと長いです)
こちらも基本方針は戦闘画面の選択ウィンドウと同じです。
「IMessageCallback」のインタフェースを実装していて、OnFinishedShowMessage()のメソッドでコールバックを受け取るようにしています。
1ページあたりの項目数をreadonlyの変数として定義していて、ここでは8に設定してあります。1ページあたりの項目数については、アイテムに関する処理を行うクラスでも使用するので、InitializeControllers()のメソッド内で渡しています。今思えば選択ウィンドウの方もハードコーディングではなく変数にしておけばよかったですね(1敗)
IsPausedMessageのプロパティは、アイテムを使った時のメッセージを待つかどうかのフラグです。戦闘画面の「BattleActionProcessor」で実装したように、アイテム処理時にメッセージを表示、処理を待ち合わせてメッセージ表示が完了したらフラグをfalseにして次の処理、といった感じで処理を進められるように、こちらのクラスでプロパティを用意しています。今後魔法に関しても個別の処理クラスを用意するので、そちらからも参照できるように「MenuItemWindowController」にプロパティを実装してあります。
Update()から呼ばれるSelectItem()の処理ではキー入力を確認しています。メニュー画面のフェーズを確認して、アイテムまたは魔法以外の時はキー入力を検知しないようにしています。それぞれのキーに対応する処理を実装していて、左右の矢印キーではページの切り替え、上下の矢印キーでは項目選択の切り替えを行います。ページの切り替えについては、複数ページある場合は左右ともループするようにして、最終ページから右に進むと最初のページに戻るようにしています。
上下の選択もループさせるようにしていて、画面内のアイテム数を確認して、それを元にインデックスの値を計算するようにしています。
ShowSelectedItemDescription()のメソッドではアイテムの説明を右側のウィンドウに表示するようにしています。アイテムと魔法で、それぞれの処理クラスからUIに対して説明文の情報を渡すようにしています。
PostAction()ではアイテムや魔法を使用した後の処理を行います。アイテム使用でリストの要素が減るケースもあるので、CheckSelectionPosition()のメソッドを使って、選択中のインデックスで不整合が起きないように確認処理も入れています。例えば末尾のアイテムを使用したら、カーソルの位置をそのひとつ前に移動させる、といった感じです。
ウィンドウ内でアイテムに関する処理を制御するクラス
続いて、同じフォルダでアイテムに関する部分を担当するMonoBehaviourのスクリプトファイルを作成します。名前は [MenuItemWindowItemController] にしました。ちょっとややこしいですが、メニューで項目を表示するウィンドウのうち、アイテムに関して制御するクラス、といった位置付けです。戦闘画面では「SelectionItemWindow」にしていたのでその流れにしています。

作成した「MenuItemWindowItemController」の中身は以下のように記載しました。
こちらも戦闘画面の選択ウィンドウと基本方針は同じです。1ページあたりの項目数は「MenuItemWindowController」から渡してもらって、それを元にページ数などを計算しています。
Inspectorウィンドウからアイテムの所持数を設定する関係で、存在しないIDのアイテムを入力することを考慮して、IDの確認処理も入れておきます。存在するIDのアイテムをリストとして保持するため、「_validPartyItemInfoList」のフィールドを用意して、InitializeItemInfo()のメソッド内でリストに要素を追加していきます。
存在しないIDのアイテム情報は削除することも考えましたが、何らかの要因でアイテムデータが欠落して、存在しないIDとみなされて所持数が0になり、アイテムデータが復活した時に消えていた……なんてことが起きるとユーザ的にショックが大きいので、データ上は残しておいて、画面への表示が行われないようにしたいと思います。
アイテムの使用処理を行うクラス
同じフォルダでアイテムの使用処理を行うクラス用にMonoBehaviourのスクリプトファイルを作成します。名前は [MenuProcessorItem] にしました。

作成した「MenuProcessorItem」の中身は以下のように記載しました。
戦闘画面のように統合的な処理クラスを用意するのではなく、担当クラス内で個別に処理していきます。といっても使用の処理の基本形は「BattleActionProcessorItem」から持ってきていて、UseSelectedItem()のメソッドでデータ上の使用処理を行い、ShowItemHealMessage()のコルーチンでメッセージ処理を行うようにしています。
コルーチン内ではキー入力を待つようにしています。
有効なアイテムのリストを扱っている関係で、アイテムの使用処理が終わったら、「MenuItemWindowItemController」に対して完了を通知して、そこでリストの確認を行うようにしています。これは、使用処理で大元のパーティアイテムのリストは変わりますが、アイテム制御のクラスで持っている有効なアイテムリストでも変更を確認したいためです。例えば薬草を使い切ったら、表示用のリストでもそれが反映されるようになります。
既存のクラスの変更
作成したクラスに合わせて、既存のクラスも変更を加えていきます。変更したいクラスは以下の通りです。
- MenuManager
- CharacterStatusSetter
MenuManagerの変更
「MenuManager」ではアイテム画面の呼び出し部分を追加します。また、メッセージウィンドウへの参照なども追加していきます。
フィールド部分では、「TopMenuWindowController」と「MenuItemWindowController」への参照用フィールドを追加しています。
Start()のメソッドの下に、マップ上のメッセージウィンドウへの参照を返すGetMessageWindowController()のメソッドを追加します。このメソッドはアイテムに関する処理を行うクラスで使用しています。
メニュー選択の分岐で、アイテム画面を開く処理を追加します。ShowItemMenu()のメソッドでは制御クラスの準備をしてから表示するようにしています。アイテムを使用する際には、連続で使用できるように「MenuManager」へはコールバックを行いませんが、キャンセルボタンで戻る際にはOnItemCanceled()のメソッドでコールバックするようにします。ちなみに、同フレームでのキー入力検知を避けるため、「MenuItemWindowController」でキャンセルボタンが押された場合はHideProcess()のコルーチンで1フレーム待ってからこちらにコールバックしています。
CharacterStatusSetterの変更
キャラクターの初期ステータスをセットするクラスの「CharacterStatusSetter」にて、アイテムの設定を行えるようにします。「BattleTester」と同じように、リストでアイテム情報を保持して、Inspectorウィンドウで設定できるようにしましょう。以下の「_partyItemInfoList」のフィールドがそれに該当します。
また、Update()の中ではアイテムをセットする処理も追加しました。
クラスの末尾に、パーティ内のアイテムをセットするメソッドであるSetPartyItems()を追加しました。
スクリプトのアタッチ
スクリプトファイルを保存したら、ゲームオブジェクトにアタッチします。
SelectionItemControllerのアタッチ
以前Prefabから削除してしまった「SelectionItemController」を再度アタッチします。UI作成時は個別のクラスを作るつもりでいましたが、よくよく考えるとそのまま使えそうでした。二度手間で申し訳ないですが、再びアタッチしてゲームオブジェクトをアサインします。
Hierarchyウィンドウから「MenuItemSlot_0」のゲームオブジェクトを選択し、Inspectorウィンドウにて「SelectionItemController」のスクリプトをアタッチします。カーソルや、名前、数量のテキストもアサインしましょう。

他のPrefabに反映するため、「Overrides」のボタンから変更確認のウィンドウを開き、[Apply All] のボタンをクリックして適用します。念の為他のアイテムスロットのゲームオブジェクトにも変更が反映されていることを確認しましょう。

MenuItemUIControllerのアタッチ
Hierarchyウィンドウから「ItemMenuParent」のゲームオブジェクトを選択し、Inspectorウィンドウから「MenuItemUIController」のスクリプトをアタッチします。フィールドに対応するゲームオブジェクトについてもアサインしておきます。リストで8つ追加するのはちょっと大変でしたね……。

MenuItemWindowItemControllerのアタッチ
続いて、アイテムに関する処理を行うクラスをアタッチします。Hierarchyウィンドウからゲームオブジェクトを作成していきますが、先に「MenuItemWindowController」のゲームオブジェクトを作成して、その子オブジェクトにしたいと思います。
Hierarchyウィンドウで「MenuManager」を選択して空のゲームオブジェクトを作成します。名前は [MenuItemWindowController] にしました。さらにその子オブジェクトを2つ作成し、名前をそれぞれ [MenuItemWindowItemController] と [MenuProcessorItem] にしました。魔法担当のクラスについても、後ほどこちらに並ぶ予定です。

作成した「MenuItemWindowItemController」のゲームオブジェクトを選択し、Inspectorウィンドウから「MenuItemWindowItemController」のスクリプトをアタッチします。

同様に「MenuProcessorItem」のゲームオブジェクトを選択し、「MenuProcessorItem」のスクリプトをアタッチします。

MenuItemWindowControllerのアタッチ
先ほど作成した「MenuItemWindowController」のゲームオブジェクトに、「MenuItemWindowController」のスクリプトをアタッチします。UIを制御するクラス、アイテムに関する処理を行うクラスへの参照もそれぞれアサインします。

MenuManagerへの参照のアサイン
「MenuManager」でもフィールドを追加したので、こちらも参照をアサインしておきます。

動作確認
スクリプトをアタッチしたら動作確認を行います。テスト用に、「CharacterStatusSetter」のInspectorウィンドウからアイテムをいくつか設定しておきましょう。ゲーム内の仕様としては、1つのIDに対して1枠ですが、テストを行う観点では同じIDのアイテムがリスト内にあってもいいので、ページ送りできるくらいのアイテムを登録するとグッドです。アイテムの使用時の処理は、アイテムIDで検索して最初に見つかったアイテム情報を対象にするので、薬草を複数登録した場合は先頭の薬草から使われていきます。
また、存在しないIDを登録した場合は、画面上には表示されません。

たくさん登録してみて、左右のページ送りについても確認しておきましょう。

ここまでの動作が確認できれば今回は完了です。思ったより長くなりましたね。お疲れ様でした。
今回のブランチ
まとめ
今回はメニュー画面のアイテム機能について動作を実装しました。色々と気になる部分を修正していたらついコードが長くなってしまったので、いつかリファクタリングしないとですね(遠い目)
次回はメニュー画面の魔法の機能について動作を実装します。
ゲーム開発の攻略チャートを作りました!
-
前の記事
【Unity】RPGを作るチュートリアルその68 マップ上のメッセージウィンドウの動作を実装 2025.04.21
-
次の記事
記事がありません
コメントを書く