見出し画像

【Unity】3Dローグライクゲームの作り方〜Step14-8〜

前回の記事はこちら
前回は倉庫インベントリのアイテムを入れたり出したりしました。

倉庫内のアイテムをソートする

今回は倉庫内のアイテムをソートするところから始めたいと思います。
今回の仕様はソートキーを押すとWeaponから順に前に出てくるアイテムの種類が変わるというものです。その他は普通のインベントリソートと同じです。
早速行なっていきましょう。まずはソートキーを定義するのを忘れていたのでKeyConfigクラスから触ります。

// EType内に以下を追記
WAREHOUSESORT = KeyCode.R,

次にInventoryクラスにメソッドを追記しましょう。

/**
* インベントリ内を指定された種類->アイテムID->+値でソート
*/
public void Sort(EItemType type)
{
   System.Comparison<Item> s = (a, b) =>
   {
       if (a.id == b.id) return a.extPoint - b.extPoint;
       if (a.type != b.type)
       {
           if (a.type == type) return -1;
           if (b.type == type) return 1;
       }
       return a.id - b.id;
   };
   items.Sort(s);
   isSort = !isSort;
}

最後にWareHouseActionクラスを変更します。

// パラメーターを追加
public Text sortText;
private EItemType sortType = EItemType.Weapon;

// メソッドを変更
private void KeyInput(bool isAction)
{
   if (!isOpen && isAction)
       OpenWindow();
   else if (KeyConfig.GetKeyDown(KeyConfig.EType.WAREHOUSESORT))
   {
       display.inventory.Sort(sortType);
       display.Show();
       sortText.text = sortType == EItemType.Unknown ? "None" : sortType.ToString();
       sortType = (EItemType)(((int)sortType + 1) % System.Enum.GetNames(typeof(EItemType)).Length);
   }
   else if (isOpen && KeyConfig.GetKeyDown(KeyConfig.EType.WAREHOUSECLOSE))
       OpenWindow();
}

public Item InventoryInsertItem(Item it)
{
   int selectItemIndex = display.GetSelectItemIndex();
   itemInventory.Insert(selectItemIndex, it);
   display.Show();
   Item item = selectItem;
   sortType = EItemType.Weapon;
   sortText.text = "None";
   return item;
}

実行してみます。以下のようになればOKです。

スクリーンショット 2020-11-13 8.05.29

タイプがPortionのものが先頭になった

コインを預け出しするウィンドウ

すっかり忘れていましたが、コインを預けられるようにするのでしたね。
という訳で右シフトキーを押すことでコインを預けられるようにします。
まずはウィンドウの外形から作ります。イメージはこんな感じです。

倉庫預金サンプル

これをUnityエディタ上で再現します。筆者はこうなりました。

スクリーンショット 2020-11-13 12.41.28

ヒエラルキータブはこんな感じです。

スクリーンショット 2020-11-13 13.01.40

これを開けたり閉じたりするスクリプトを書きます。
「WareHouseMoneyAction」スクリプトを作成し、そこに以下のように記述して下さい。
※2020/11/13 パラメーター名に誤字があった為修正しました。

using UnityEngine;
using UnityEngine.UI;

public class WareHouseMoneyAction : MonoBehaviour
{
   public WareHouseAction wareHouseAction;
   public GameObject depositWindow;
   public Text addText1;
   public Text addText2; // 2020/11/13変更
   public Text wareHouseMoneyText;
   public Text playerMoneyText;
   public float inputHoldDelay = 0.1f;

   private EAct action = EAct.KeyInput;
   private int open = 0;
   private int money = 0;
   private float inputTime = 0;

   // 独自の更新メソッド
   public void Proc(bool isDeposit = true)
   {
       switch (action)
       {
           case EAct.KeyInput: KeyInput(isDeposit); break;
           case EAct.ActBegin: ActBegin(); break;
           case EAct.Act: Act(); break;
           case EAct.ActEnd: ActEnd(); break;
           case EAct.MoveBegin: MoveBegin(); break;
           case EAct.Move: Move(); break;
           case EAct.MoveEnd: MoveEnd(); break;
           case EAct.TurnEnd: TurnEnd(); break;
       }
   }

   /**
   * 現在の行動状態を返す
   */
   public EAct GetAction() => action;

   /**
   * 金庫画面を開く
   */
   public void OpenWindow() => action = EAct.MoveBegin;

   /**
   * 待機中
   */
   private void KeyInput(bool isDeposit = true)
   {
       if (open == 0)
       {
           open = isDeposit ? 1 : -1;
           OpenWindow();
       }
       else if (Mathf.Abs(open) > 0 && KeyConfig.GetKeyDown(KeyConfig.EType.WAREHOUSECLOSE))
       {
           open = 0;
           OpenWindow();
       }
   }

   /**
   * アクションを始める
   */
   private void ActBegin()
   {
       KeyInput();
   }

   /**
   * アクション中
   */
   private void Act()
   {
       action = EAct.ActBegin;
   }

   /**
   * アクションが終わった
   */
   private void ActEnd()
   {
       action = EAct.TurnEnd;
   }

   /**
   * 移動を始める
   */
   private void MoveBegin()
   {
       if (Mathf.Abs(open) > 0)
           gameObject.SetActive(true);
       if (open > 0)
           depositWindow.SetActive(true);
       action = EAct.Move;
   }

   /**
   * 移動中
   */
   private void Move()
   {
       action = EAct.MoveEnd;
   }

   /**
   * 移動が終わった
   */
   private void MoveEnd()
   {
       if (Mathf.Abs(open) > 0) action = EAct.ActBegin;
       else
       {
           depositWindow.SetActive(false);
           action = EAct.TurnEnd;
       }
   }

   /**
   * ターンが終わった
   */
   private void TurnEnd()
   {
       action = EAct.KeyInput;
   }
}

このスクリプトはMoneyWindowsにあたるオブジェクトにアタッチしておいて下さい。
KeyConfigクラスのETypeに追記します。

WAREHOUSEDEPOSIT = KeyCode.RightShift,
WAREHOUSEWITHDRAW = KeyCode.LeftShift

WareHouseActionクラスに追記します。

// パラメーターを追記
public WareHouseMoneyAction wareHouseMoneyAction;

// メソッドに追記
private void KeyInput(bool isAction)
{
   if (!isOpen && isAction)
       OpenWindow();
   else if (KeyConfig.GetKeyDown(KeyConfig.EType.WAREHOUSESORT))
   {
       display.inventory.Sort(sortType);
       display.Show();
       sortText.text = sortType == EItemType.Unknown ? "None" : sortType.ToString();
       sortType = (EItemType)(((int)sortType + 1) % System.Enum.GetNames(typeof(EItemType)).Length);
   }
   else if (KeyConfig.GetKeyDown(KeyConfig.EType.WAREHOUSEDEPOSIT))
   {
       wareHouseMoneyAction.Proc(true);
       action = EAct.Act;
   }
   else if (KeyConfig.GetKeyDown(KeyConfig.EType.WAREHOUSEWITHDRAW))
   {
       wareHouseMoneyAction.Proc(false);
       action = EAct.Act;
   }
   else if (isOpen && KeyConfig.GetKeyDown(KeyConfig.EType.WAREHOUSECLOSE))
       OpenWindow();
}

private void Act()
{
   selectItem = null;
   if (wareHouseMoneyAction.GetAction() == EAct.KeyInput)
       action = EAct.ActBegin;
}

コンポーネントの設定を終えたら、実行してみます。

スクリーンショット 2020-11-13 14.53.19

開けましたね。同様にコイン引き出しのウィンドウも作成します。

倉庫引き出しサンプル

スクリーンショット 2020-11-13 15.03.17

スクリーンショット 2020-11-13 15.03.56

WareHouseMoneyActionクラスに追記して下さい。

// パラメーターを追加
public GameObject withdrawWindow;

// メソッドを変更private void MoveBegin()
{
   if (Mathf.Abs(open) > 0)
       gameObject.SetActive(true);
   if (open > 0)
       depositWindow.SetActive(true);
   if (open < 0)
       withdrawWindow.SetActive(true);
   action = EAct.Move;
}

private void MoveEnd()
{
   if (Mathf.Abs(open) > 0) action = EAct.ActBegin;
   else
   {
       depositWindow.SetActive(false);
       withdrawWindow.SetActive(false);
       gameObject.SetActive(false);
       action = EAct.TurnEnd;
   }
}

左シフトキーを押すとコインを引き出す画面を開けます。

スクリーンショット 2020-11-13 15.14.46

所持コインの記述箇所の変更

色々考えたのですが、コインを持たせる箇所をActorParamsControllerクラスからItemInventoryクラスに変えようと思います。という訳で以下の箇所を全て変更して下さい。
まずはActorParamsControllerクラスです。

// 以下のパラメーターを削除
public int money = 0;

次はItemInventoryクラスです。

// 以下のパラメーターを追加
public int money = 0;

ActorUseItemsクラスのSellメソッドを以下のように変えて下さい。

public bool Sell(Item it)
{
   bool isEnd = false;
   if (it.type == EItemType.Stone)
   {
       StoneInventory si = GetComponent<StoneInventory>();
       isEnd = si.Remove(it);
   }
   else isEnd = inventory.Remove(it);
   if (isEnd)
   {
       inventory.money += it.bidprice;
       Message.Add(39, it.name);
       Message.Add(40, it.bidprice + "");
   }
   return true;
}

ShopActionクラスを変更して下さい。

private void ActBegin()
{
   if (isCursorMoving)
   {
       isCursorMoving = !MoveSelectItem();
       return;
   }
   if (selectItem == null)
   {
       isCursorMoving = !MoveSelectItem();
       if (isCursorMoving) return;
       KeyInput(false);
       SelectItem();
   }
   else
   {
       MoveSelectSubMenuItem();
       SelectSubMenuItem();
       UnSelectItem();
   }
   playerMoney.text = playerInventory.money + "";
}

private void Act()
{
   if (subMenu.GetSelectItemMethod() == "Buy")
   {
       if (playerInventory.money >= selectItem.price)
       {
           if (playerInventory.Add(selectItem))
           {
               playerInventory.money -= selectItem.price;
               itemInventory.Remove(selectItem);
               Message.Add(41, selectItem.name);
               Message.Add(42, selectItem.price + "");
           }
           else Message.Add(44);
       }
       else Message.Add(43);
   }
   display.Show(true);
   selectItem = null;
   action = EAct.ActBegin;
}

ActorSaveDataから以下のパラメーターを削除して下さい。

public int money;

InventorySaveDataに以下のパラメーターを追記して下さい。

public int money;

最後にSaveDataManagerを以下のように変更して下さい。

private ActorSaveData MakeActorData(Transform actor)
{
   ActorMovement move = actor.GetComponent<ActorMovement>();
   ActorSaveData actorSaveData = new ActorSaveData();
   actorSaveData.grid = new Pos2D();
   actorSaveData.grid.x = move.grid.x;
   actorSaveData.grid.z = move.grid.z;
   actorSaveData.direction = move.direction;
   ActorParamsController param = actor.GetComponent<ActorParamsController>();
   actorSaveData.parameter = param.GetParameter();
   actorSaveData.conditions = param.GetConditions();
   actorSaveData.itemInventory = MakeInventoryData(actor.GetComponent<ItemInventory>());
   if (param.parameter.id == EActor.PLAYER)
       actorSaveData.stoneInventory = MakeInventoryData(actor.GetComponent<StoneInventory>());
   return actorSaveData;
}

private void LoadActorData(ActorSaveData data, Transform actor)
{
   ActorMovement move = actor.GetComponent<ActorMovement>();
   move.SetPosition(data.grid.x, data.grid.z);
   move.SetDirection(data.direction);
   ActorParamsController param = actor.GetComponent<ActorParamsController>();
   param.SetParameter(data.parameter);
   param.SetConditions(data.conditions);
   LoadInventoryData(data.itemInventory, actor.GetComponent<ItemInventory>());
   if (data.parameter.id == EActor.PLAYER)
       LoadInventoryData(data.stoneInventory, actor.GetComponent<StoneInventory>());
}

private InventorySaveData MakeInventoryData(Inventory inventory)
{
   InventorySaveData inventorySaveData = new InventorySaveData();
   inventorySaveData.items = inventory.GetAllItem();
   inventorySaveData.maxItemNum = inventory.itemNumMax;
   if (inventory is ItemInventory) inventorySaveData.money = ((ItemInventory)inventory).money;
   return inventorySaveData;
}

private void LoadInventoryData(InventorySaveData data, Inventory inventory)
{
   inventory.SetAllItem(data.items, data.maxItemNum);
   if (inventory is ItemInventory) ((ItemInventory)inventory).money = data.money;
}

実行してみて、今まで通り売り買いできることを確かめておいて下さい。

というところで今回はここまでです。
次回は実際にコインを預けたり引き出したりできるようにします。
(最近投稿が遅れ気味ですみません......)

この記事が気に入ったらサポートをしてみませんか?