【Unity】RPGを作るチュートリアルその100 お店のアイテム売却処理を実装

【Unity】RPGを作るチュートリアルその100 お店のアイテム売却処理を実装

シンプルなRPGをUnityで作るチュートリアルシリーズの100回目です。祝100回! 長いチュートリアルはこれもうチュートリアルの範囲じゃないな? と思ったりもしますが、終わりは見えてきているので引き続き頑張って参りましょう。僕たちの戦いはこれからだ!(完)

第99回ではお店でアイテムを買う動作を実装しました。

今回はお店でアイテムを売る動作を実装していきます。今回の作業でお店に関する部分は完了です。

 

 

制作環境

MacBook Pro 2023 Apple M2 Max

Unity6 (6000.0.30f1) Silicon

 

作業内容と順序

シンプルなRPGを作る上でどんな作業が必要か、どんな順番で作っていくと良さそうか、別ページで検討しました。基本的にこの流れに沿って進めていきます。

 

チュートリアルの一覧

このシリーズ全体の一覧は以下のページにまとめています。

 

前回の内容

前回はお店でアイテムを買う動作を実装しました。

 

お店でアイテムを売却する処理

お店でのアイテム購入ができるようになったので、「売る」を選んだ時に所持品を売る機能についても実装していきます。

お店に関するクラスの構成としては、

  • お店全体の管理クラス
    • お店の処理完了を通知するコールバック用インタフェース
    • お店の選択肢用のコールバック用インタフェース
    • お店の選択肢用の制御クラス
    • お店の選択項目を表現するEnum
  • お店のアイテム画面を制御するクラス
    • 購入に関するアイテム制御のクラス
    • 購入処理を行うクラス
    • 売却に関するアイテム制御のクラス
    • 売却処理を行うクラス

のように処理範囲を分けており、今回は売却に関するアイテム制御のクラス、売却処理を行うクラスについて実装していきます。

また、前回作成したお店のアイテム画面を制御するクラスの「ShopItemWindowController」やお店全体を管理するクラスの「ShopManager」についても、売却に関連する部分を変更していきましょう。

 

売却に関するアイテム制御のクラスの作成

購入時と同じように、アイテム画面に関する機能のうち、売却に関する部分の機能をまとめたクラスを作成していきます。購入時は品揃えのアイテムIDリストからアイテムデータを取得していたのに対し、売却時は所持品の情報からリストを作成していきます。

Projectウィンドウから「Assets/Scripts/Shop」のフォルダを開き、MonoBehaviourのスクリプトファイルを作成します。名前は [ShopItemWindowSellController] にしました。

売却に関する制御を行うクラス
売却に関する制御を行うクラス

 

作成した「ShopItemWindowSellController」の中身は以下のように記載しました。

基本的な構成は購入に関する制御を行う「ShopItemWindowBuyController」と一緒です。

こちらではパーティの所持品を参照するため、「PartyItemInfo」のIDを使ってアイテムデータを取得します。所持数が0になったアイテムについては「PartyItemInfo」のリストから削除されるので、リスト内にあるアイテムが売却対象になります。選択を検証するIsValidSelection()のメソッドでは念の為個数もチェックしています。

SetPageItem()では、アイテム名の右側にあるテキストエリアに売値をセットしています。売値の計算に関しては、前回「ValueSettings」内に追加した「SellPriceMultiplier」の定義値を使って計算しています。floatとして計算した後、intにキャストして最終的な売値にしています。intにキャストする過程で小数点以下は切り捨てになっています。

 

売却処理を行うクラスの作成

売却処理として、所持金の増加やアイテム数の減少などを行うクラスも作成します。

Projectウィンドウから「Assets/Scripts/Shop」のフォルダにて、MonoBehaviourのスクリプトファイルを作成します。名前は [ShopProcessorSell] にしました。

売却処理を行うクラス
売却処理を行うクラス

 

作成した「ShopProcessorSell」の中身は以下のように記載しました。

SellSelectedItem()のメソッドでは引数のアイテムデータを元に、アイテム所持数の変更処理と、所持金を増加させる処理を行います。所持金の増加に関しては「ValueSettings」の「SellPriceMultiplier」の定義値を使って計算しています。計算方法は「ShopItemWindowSellController」内のSetPageItem()のメソッド内で記載したものと一緒です。

処理が完了したら「ShopItemWindowSellController」内のOnFinishedItemProcess()に完了を通知します。

 

既存のクラスの変更

今回作成したクラスと繋ぎ合わせるため、以下のクラスも変更していきます。

  • ShopItemWindowController
  • ShopManager

 

ShopItemWindowControllerの変更

「ShopItemWindowController」では売却に関連する部分を追加していきます。前回購入に関する部分を実装する際に、売却に関する分岐を作っておいたので、そこに処理を入れていきます。

フィールドでは既存の「_buyController」の下に「_sellController」のフィールドを追加します。

 

 

既存のGetBuyController()のメソッドの下に、同じくコントローラへの参照を取得するGetSellController()を追加しました。また、InitializeControllers()のメソッド内では、売却に関するクラスの初期化処理も行うようにしました。

 

 

検証を行うメソッドのIsValidIndex()とIsValidSelection()では、売却の分岐内で対応するメソッドを呼び出すようにしました。

 

 

ページ数に関する情報を取得するメソッドでも分岐内で対応するものを追加します。

 

CheckSelectionPosition()とShowSelectedItemDescription()でも売却の分岐に処理を追加していきます。

ShowSelectionCursor()は変更なしです。

 

 

SetPageElement()、OnPressedConfirmButton()でも売却の分岐で処理を追加します。

今更ですが、ここまで分岐が多くなると管理も大変なので、対応するコントローラを返すメソッドを作っても良かったかもしれません。他の画面でも同様なので、チュートリアル完了後のリファクタリング対象として考えてみます。

 

ShopManagerの変更

「ShopManager」では売却時の確認メッセージを表示するようにしたいと思います。

 

既存の「_shopProcessorBuy」のフィールドの下に「_shopProcessorSell」のフィールドを追加しました。この参照はInspectorウィンドウからアサインしましょう。

 

 

StartShopProcess()のメソッドでは「ShopProcessorSell」の初期化処理を追加しました。

 

 

購入または売却確認の選択肢を選んだ時のOnSelectedOption()では、「売る」を選んでいる時の処理を追加しました。

 

 

アイテム画面でアイテムを選択した時に呼ばれるOnSelectedItem()のメソッドでは売却時の分岐に処理を追加しました。

ShowSellMessage()は売却時のメッセージ表示の処理を行うメソッドです。流れは購入時と同じで、メッセージが売却用のものになっています。

 

スクリプトのアタッチ

作成したスクリプトをアタッチしていきましょう。

Hierarchyウィンドウから「ShopManager」の子オブジェクトとして空のゲームオブジェクトを2つ作成します。名前はそれぞれ [ShopItemWindowSellController][ShopProcessorSell] にしました。

ゲームオブジェクトの作成
ゲームオブジェクトの作成

 

「ShopItemWindowSellController」のゲームオブジェクトを選択し、Inspectorウィンドウから同名のスクリプトファイルをアタッチします。

アイテム画面で売却に関する処理を行うクラス
アイテム画面で売却に関する処理を行うクラス

 

同様に「ShopProcessorSell」のゲームオブジェクトを選択し、Inspectorウィンドウから同名のスクリプトファイルをアタッチします。

売却に関する処理を行うクラス
売却に関する処理を行うクラス

 

既存のクラスにも参照をアサインしていきます。「ShopItemWindowController」では「ShopItemWindowSellController」への参照をアサインします。

参照のアサイン
参照のアサイン

 

「ShopManager」では「ShopProcessorSell」への参照をアサインします。

こちらも参照をアサイン
こちらも参照をアサイン

 

動作確認

アイテムを売る時のお店の動作を確認してみましょう。確認前に、「Map_0001_Village」を非表示に、「ShopItemParent」も非表示にしておきます。

宝箱からゴールドを入手した後、店主のおっちゃんに話しかけて、任意のアイテムを購入します。その後、お店の選択肢で「売る」を選び、売却できるかどうかを確認しましょう。

  • 売却時に提示されるゴールドが買値の半額になっていること
  • メニューのアイテム画面て売却したアイテムの所持数が減っていること(または表示されないこと)
  • ステータス画面でゴールドが反映されていること

確認していきます。

アイテム売却の確認
アイテム売却の確認

 

細かい修正

動作確認をしていて気になったのが、アイテムを所持していない状態で「売る」の画面を開くと、何も選択していないはずなのに装備によるパラメータ変動が表示される点です。これを修正していきます。

変動は表示されない想定でした
変動は表示されない想定でした

 

「ShopItemWindowController」内のSetEquipmentInformation()のメソッドにて、IDによるアイテム取得でnullになった際に、現在の装備品IDを取得せずに分岐を抜けていたため、ステータス情報がnullでない場合はアイテムデータの確認前に装備品のIDをセットするようにしました。

これにより、itemCategoryによる分岐でelseが必要なくなったので削除しました。

 

上記の修正を保存してゲームを実行すると、以下のようにアイテムを所持していない場合にも、パラメータ変動が発生しなくなります。

これで安心
これで安心

 

100回目のチュートリアルなので、気づいたエラーについてはつい修正してしまいました。見栄です。

 

今回のブランチ

 

まとめ

今回はお店でアイテムを売る動作を実装しました。売値の倍率については定数クラスなどで定義しておくと一律で反映できて便利です。また、今回でお店に関する作業は完了です。後半のUI作成はなかなかメンタルにきますが、しんどい部分はおそらく終わり……あっタイトル画面があ(ry

次回はイベントから戦闘を呼び出す機能を実装します。

 

     

ゲーム開発の攻略チャートを作りました!

CTA-IMAGE

「ゲームを作ってみたいけど、何から手を付けていいか分からない!」


そんなお悩みをお持ちの方向けに、todoがアプリをリリースした経験を中心に、ゲーム作りの手順や考慮すべき点をまとめたe-bookを作成しました。ゲーム作りはそれ自体がゲームのように楽しいプロセスなので、「攻略チャート」と名付けています。


ゲームを作り始めた時にぶつかる壁である「何をしたら良いのか分からない」という悩みを吹き飛ばしましょう!