【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です。
タイプがPortionのものが先頭になった
コインを預け出しするウィンドウ
すっかり忘れていましたが、コインを預けられるようにするのでしたね。
という訳で右シフトキーを押すことでコインを預けられるようにします。
まずはウィンドウの外形から作ります。イメージはこんな感じです。
これをUnityエディタ上で再現します。筆者はこうなりました。
ヒエラルキータブはこんな感じです。
これを開けたり閉じたりするスクリプトを書きます。
「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;
}
コンポーネントの設定を終えたら、実行してみます。
開けましたね。同様にコイン引き出しのウィンドウも作成します。
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;
}
}
左シフトキーを押すとコインを引き出す画面を開けます。
所持コインの記述箇所の変更
色々考えたのですが、コインを持たせる箇所を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;
}
実行してみて、今まで通り売り買いできることを確かめておいて下さい。
というところで今回はここまでです。
次回は実際にコインを預けたり引き出したりできるようにします。
(最近投稿が遅れ気味ですみません......)
この記事が気に入ったらサポートをしてみませんか?