見出し画像

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

前回の記事はこちら
前回はマップデータのアイテムオブジェクトをアイテムIDで記述できるようにして、アイテム周りのセーブ・ロード処理を更新しました。

詳細表示用のウィンドウを作る

それでは今回は予告した通りアイテムの詳細表示から始めたいと思います。
まず最初に詳細表示用のウィンドウを作成したいと思います。
ヒエラルキータブのInventoryWindow内に空のオブジェクトを作成します。そして、以下のように設定して下さい。

スクリーンショット 2020-05-18 3.29.40

このDetailWindowの階層下にパネルを作成し、以下のように設定します。

スクリーンショット 2020-05-18 3.34.26

このPanelの階層下に更にテキストを作成し、以下のように設定します。

スクリーンショット 2020-05-18 8.41.20

これで必要最低限のウィンドウは作成できました。しかしこれだけでは味気ないので、三角形を追加して吹き出しのようにしてみます。
まず、Prefabs/Spriteフォルダ内で右クリック→「作成」→「スプライト」→「三角形」を選択し、三角形のスプライトを作成します。
次にPrefabsフォルダ内のItemSlotの階層下に画像(Image)オブジェクトを作成し、ソース画像に先ほど作成した三角形のスプライトをドラッグ&ドロップで設定します。そして、以下のように設定して下さい。

スクリーンショット 2020-05-18 4.57.48

後は色などはお好みで設定しましょう。
最終的に以下のようになればOKです。

スクリーンショット 2020-05-18 4.58.58

三角形の画像は非アクティブにしておいて下さい。

詳細を表示してみる

それではスクリプトに移りましょう。ItemSlotDisplayスクリプトを以下のように書き換えて下さい。

// 以下のパラメーターを追加
public GameObject detail;

// 以下のメソッドを追加
/**
* アイテムの詳細を表示する
*/
private void ShowItemDetail()
{
   int idx = prevViewSelectItemIndex + leadShowItemIndex;
   Item it = idx == inventory.itemNumMax ? footItem : inventory.Get(idx);
   if (it == null) detail.GetComponentInChildren<Text>().text = "";
   else detail.GetComponentInChildren<Text>().text = it.detail;
   for (int i = 0; i < maxShowItemNum; i++)
   {
       Transform slot = content.transform.GetChild(i);
       slot.GetChild(2).gameObject.SetActive(false);
   }
   Transform currentSlot = content.transform.GetChild(prevViewSelectItemIndex);
   currentSlot.GetChild(2).gameObject.SetActive(true);
}

// MoveSelectとShowメソッドの最後に以下を追記
ShowItemDetail();

ShowItemDetailメソッドは現在選択されているアイテムスロットのアイテムがあれば詳細表示し、そのアイテムスロットのみ吹き出し口を表示しています。
ビルドしたら、Item Slot DisplayコンポーネントのDetailにDetailWindowを設定しておいて下さい。
テストしてみましょう。以下のようにアイテムの詳細を表示できていればOKです。

スクリーンショット 2020-05-18 5.26.00

装備フラグの追加とアイテムデータ関連の整理

装備アイテムを装備できるようにしたいと思います。
まず、装備しているかどうかのフラグをItemクラスに追加します。

// Itemクラスに以下を追記
public bool isEquip;

フラグを追加したので、関連するクラスのメソッドも変更しておく......のですが、毎回似たような記述を何回もするのは大変です。なので、ItemクラスにGetメソッドを追加して、これらの代わりにします。

/**
* アイテムデータのコピーを返す
*/
public Item Get()
{
   Item p = new Item();
   p.id = id;
   p.type = type;
   p.name = name;
   p.prefab = prefab;
   p.sprite = sprite;
   p.isEquip = isEquip;
   p.atk = atk;
   p.def = def;
   p.hp = hp;
   p.food = food;
   p.dmg = dmg;
   p.detail = detail;
   return p;
}

同時に関連するクラスも変更していきます。まずはItemParamsControllerクラスのメソッドを変更します。

public Item GetParams()
{
   return parameter.Get();
}

public void SetParams(Item it)
{
   parameter = it.Get();
}

次にInventoryクラスのメソッド二つを変更します。

public Item[] GetAllItem()
{
   Item[] itemList = new Item[items.Count];
   for (int i = 0; i < items.Count; i++)
   {
       itemList[i] = items[i].Get();
   }
   return itemList;
}

public void SetAllItem(Item[] itemList, int maxNum)
{
   List<Item> items = new List<Item>();
   int itemCnt = itemList.Length < maxNum ? itemList.Length : maxNum;
   for (int i = 0; i < itemCnt; i++)
   {
       items.Add(itemList[i].Get());
   }
   itemNumMax = maxNum;
   this.items = items;
}

InventoryEditorクラスを作成した方はこのメソッドも変更します。

private void SetItem(Item it, ref Item parameter)
{
   parameter = it.Get();
}

もっと早くこうしていればよかったですね......。すみません。

サブメニューに装備の項目を追加

次に、装備アイテムを選んでいるときは装備を選べるようにします。まずInventoryActionクラスのSelectItemメソッドを変更します。

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

装備アイテム(~ID:1000)なら「使う」コマンドから「装備」コマンドに変更するようにしています。ただし、装備アイテムを装備するにはそのアイテムを所持していないといけないので、拾って身に付ける事はできません。なので「PickUpEquip」は指定してはいけません。
次にActorParamsControllerクラスに内部クラス「Equipment」を定義し、新しいパラメーターとメソッドを追加します。

// 内部クラスの定義
[System.Serializable]
public class Equipment
{
   public Item weapon;
   public Item armor;
}

// このパラメーターとメソッドを追加
public Equipment equipment;

/**
* アイテムを装備する
*/
public void EquipItem(Item it)
{
   RemoveEquipment(it);
   if (it.type == EItemType.Weapon)
   {
       Message.Add(6, it.name);
       equipment.weapon = it;
       it.isEquip = true;
   }
   else if (it.type == EItemType.Armor)
   {
       Message.Add(6, it.name);
       equipment.armor = it;
       it.isEquip = true;
   }
}

/**
* 装備アイテムを外す
*/
public void RemoveEquipment(Item it)
{
   if (it.type == EItemType.Weapon && equipment.weapon != null && equipment.weapon.isEquip)
   {
       Message.Add(7, equipment.weapon.name);
       equipment.weapon.isEquip = false;
       equipment.weapon = null;
   }
   else if (it.type == EItemType.Armor  && equipment.armor != null && equipment.armor.isEquip)
   {
       Message.Add(7, equipment.armor.name);
       equipment.armor.isEquip = false;
       equipment.armor = null;
   }
}

EquipItemメソッドは、もし武器ならばweaponに代入し、防具ならarmorに代入しています。
最後にActorUseItemsスクリプトを開いて、新たなメソッドを追加し、またそれに伴いGetDelegateメソッドに追記します。

// メソッドを追加
/**
* 引数で渡されたアイテムを装備する
*/
public bool Equip(Item it)
{
   param.EquipItem(it);
   return true;
}

// GetDelegateメソッドのswitch文内に追記
case "Equip": return new UseItem(Equip);

ビルドしたら、SubMenuのChoice NamesとChoice Methodsの要素7にそれぞれ「装備」、「Equip」を設定しておきましょう。
テストしてみます。このようになればOKです。

スクリーンショット 2020-05-18 13.39.37

装備アイテムを選ぶと「使う」の代わりに「装備」が表示される

スクリーンショット 2020-05-18 13.39.46

装備を選択した

スクリーンショット 2020-05-18 13.40.23

EquipmentのWeaponに反映されている

しかしこのままだと、何も表示がないのでゲーム中でそのアイテムを装備しているかどうかがわかりません。
どうにかしないといけませんが、長くなってしまったので次回に回します。
恐らく明日には投稿されていますので、どうぞよろしくお願い致します。

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