見出し画像

【Unity】3Dローグライクゲームの作り方〜Step9&10-10〜

前回の記事はこちら
前回はアイテムを置けるようにして、地面にあるアイテムをインベントリウィンドウに表示できるようにしました。

地面にあるアイテム用のサブメニュー

地面にあるアイテム用のサブメニューを表示していきましょう。
サブメニューといえばSubMenuクラスですね。スクリプトを開いて、以下のように変更しましょう。

// 以下をスクリプトの最初に追記
using System;

// 以下のパラメーターを追加
private int[] choiceIndexes;

// 以下のメソッドを追加
/**
* メソッドの文字列から選択肢の順番を変える
*/
public void SetChoices(string choiceOrder)
{
   string[] choiceOrderList = choiceOrder.Replace(" ", "").Split(',');
   int maxItemNum = transform.childCount;
   for (int i = 0; i < maxItemNum; i++) transform.GetChild(i).gameObject.SetActive(false);
   maxItemNum = maxItemNum < choiceOrderList.Length ? maxItemNum : choiceOrderList.Length;
   choiceIndexes = new int[maxItemNum];
  int j = 0;
   for (int i = 0; i < maxItemNum; i++)
   {
       int idx = Array.IndexOf(choiceMethods, choiceOrderList[i]);
       if (idx < 0) continue;
       choiceIndexes[j] = idx;
       transform.GetChild(i).gameObject.SetActive(true);
       j++;
   }
}


// 以下のメソッドを変更
public string GetSelectItemMethod() => choiceMethods[choiceIndexes[selectItemIndex]];

public void Show()
{
   int i = 0;
   foreach (var text in GetComponentsInChildren<Text>())
   {
       text.text = choiceNames[choiceIndexes[i]];
       i++;
   }
   /*      省略      */
}

SetChoicesは文字列で渡されたメソッド名から、そのメソッドが登録されている場合のみ、そのインデックス値を配列に代入しています。
そうしたらInventoryクラスに以下のメソッドを追加して下さい。

/**
* インベントリがいっぱいかどうか
*/
public bool IsFull() => items.Count >= itemNumMax;

次にInventoryActionクラスのSelectItemメソッドを以下のように変更します。

private void SelectItem()
{
   if (Input.anyKeyDown && Input.GetKeyDown(KeyCode.Space))
   {
       selectItem = display.GetSelectFootItem();
       if (selectItem != null)
       {
           if (display.inventory.IsFull()) subMenu.SetChoices("PickUpUse, PickUpThrow");
           else subMenu.SetChoices("PickUp, PickUpUse, PickUpThrow");
           subMenu.Show();
           return;
       }
       selectItem = display.GetSelectItem();
       if (selectItem != null)
       {
           if (display.inventory.GetFootItem() == null) subMenu.SetChoices("Use, Put, Throw");
           else subMenu.SetChoices("Use, Replace, Throw");
           subMenu.Show();
       }
   }
}

最後にActorUseItemsクラスを以下のように変更します。

// 以下のメソッドを追加
/**
* 引数で渡されたアイテムを拾ってインベントリに加える
*/
public bool PickUp(Item it)
{
   inventory.Add(it);
   GameObject item = GetComponentInParent<Field>().GetExistItem(move.grid.x, move.grid.z);
   if (item != null) Destroy(item);
   Message.Add(8, param.actorName, it.name);
   return true;
}

/**
* 引数で渡されたアイテムを拾って使う
*/
public bool PickUpUse(Item it)
{
   Message.Add(5, param.actorName, it.name);
   GameObject item = GetComponentInParent<Field>().GetExistItem(move.grid.x, move.grid.z);
   if (item == null) return true;
   Destroy(item);
   return true;
}

/**
* 引数で渡されたアイテムを地面のアイテムと交換する
*/
public bool Replace(Item it)
{
   Message.Add(11, it.name);
   GameObject item = GetComponentInParent<Field>().GetExistItem(move.grid.x, move.grid.z);
   GameObject items = GetComponentInParent<Field>().items;
   GameObject itemObj = (GameObject)Resources.Load("Prefabs/" + it.prefab);
   GameObject item2 = Instantiate(itemObj, items.transform);
   item2.GetComponent<ItemMovement>().SetPosition(move.grid.x, move.grid.z);
   item2.GetComponent<ItemParamsController>().SetParams(it);
   inventory.Remove(it);
   if (item != null)
   {
       it = item.GetComponent<ItemParamsController>().parameter;
       Message.Add(8, param.actorName, it.name);
       inventory.Add(it);
       Destroy(item);
   }
   return true;
}

/**
* 引数で渡されたアイテムを拾って投げる
*/
public bool PickUpThrow(Item it)
{
   return true;
}

// 以下のメソッドを変更
public UseItem GetDelegate(string method)
{
   switch (method)
   {
       case "Use": return new UseItem(Use);
       case "Put": return new UseItem(Put);
       case "Throw": return new UseItem(Throw);
       case "PickUp": return new UseItem(PickUp);
       case "PickUpUse": return new UseItem(PickUpUse);
       case "Replace": return new UseItem(Replace);
       case "PickUpThrow": return new UseItem(PickUpThrow);
   }
   return new UseItem(DoNothing);
}

ビルドしたら、Sub MenuコンポーネントのChoice NamesとChoice Methodsのサイズを7にし、以下のように設定します。

スクリーンショット 2020-05-14 22.19.03

(Choice Namesの要素は自由に変えてもらって構いません。その際はChoice Methodsのメソッド名に対応する選択肢名をつけましょう)
テストしてみます。Item Num Maxの値を変えたり、アイテムを持っている状態にしたりして、色々試してみて下さい。

スクリーンショット 2020-05-15 0.48.45

アイテムスロットに空きがある時のメニュー

スクリーンショット 2020-05-15 0.49.56

アイテムスロットに空きがない状態でアイテムの上に乗った時のメニュー

確認できたところで、今回はここまでということにします。
次回は投げる処理を書いていきたいと思います。

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