見出し画像

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

前回の記事はこちら
前回はアイテムデータを読み込みました。

マップデータの変更・読み込み

今回はマップデータの改良から始めたいと思います。配置するアイテムオブジェクトの名前を以下のようにアイテムIDに変更します。

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

それができたら、LoadFieldMapスクリプトを開いて、readMapFileメソッドを以下のように変更します。

private Array2D readMapFile(string path)
{
   try
   {
       /*     省略     */
       ExcelActorData actorDatabase = Resources.Load<ExcelActorData>("Datas/ExcelActorData");
       ExcelActorData.ActorData[] actorDatas = actorDatabase.Data.ToArray();
       ExcelItemData itemDatabase = Resources.Load<ExcelItemData>("Datas/ExcelItemData");
       foreach (var objgp in map.Elements("objectgroup"))
       {
           switch (objgp.Attribute("id").Value)
           {
               case "2":
                   foreach (var obj in objgp.Elements("object"))
                   {
                       int x = int.Parse(obj.Attribute("x").Value);
                       int z = int.Parse(obj.Attribute("y").Value);
                       int pw = int.Parse(obj.Attribute("width").Value);
                       int ph = int.Parse(obj.Attribute("height").Value);
                       string name = obj.Attribute("name").Value;
                       bool isContinue = false;
                       foreach (var actorData in actorDatas)
                       {
                           if (name == actorData.prefab)
                           {
                               if (actorData.id > 0)
                               {
                                   GameObject enemyObj = (GameObject)Resources.Load("Prefabs/" + name);
                                   GameObject enemy = Instantiate(enemyObj, enemies.transform);
                                   enemy.GetComponent<ActorMovement>().SetPosition(ToMirrorX(x / pw, w), z / ph);
                                   enemy.GetComponent<EnemyOperation>().target = player;
                                   isContinue = true;
                                   break;
                               }
                               player.GetComponent<ActorMovement>().SetPosition(ToMirrorX(x / pw, w), z / ph);
                               isContinue = true;
                               break;
                           }
                       }
                       if (isContinue) continue;
                       foreach (EItem itemId in System.Enum.GetValues(typeof(EItem)))
                       {
                           if (name == itemId.ToString())
                           {
                               Item itemData;
                               if ((int)itemId > 1000) itemData = itemDatabase.Goods.Find(n => n.id == itemId);
                               else itemData = itemDatabase.Equipments.Find(n => n.id == itemId);
                               if (itemData == null) break;
                               GameObject itemObj = (GameObject)Resources.Load("Prefabs/" + itemData.prefab);
                               GameObject item = Instantiate(itemObj, items.transform);
                               item.GetComponent<ItemMovement>().SetPosition(ToMirrorX(x / pw, w), z / ph);
                               item.GetComponent<ItemParamsController>().SetParams(itemData);
                           }
                       }
                   }
                   break;
           }
       }
       return data;
   }
   catch (System.Exception i_exception)
   {
       Debug.LogErrorFormat("{0}", i_exception);
   }
   return null;
}

アイテムIDの列挙定数の数だけループを回して、一致するものがないか探し、もし見つけたらExcelItemDataからデータを取ってきています。
テストしてみましょう。以下のように配置したアイテムが表示されたらOKです。

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

アイテムがちゃんと拾えて、なおかつインベントリに名前が表示されるかどうかも確認しておきましょう。

複数の種類のアイテムをセーブ・ロードできるようにする

さてお次はセーブです。今の状態でセーブ・ロードするともれなく最初に作成したアイテムに変わってしまいます。これを防ぐために、セーブデータ関連のクラスを変更したいと思います。
ですがその前に、ItemParamsControllerクラスに以下のメソッドを追加して下さい。

/**
* アイテムパラメーターを返す
*/
public Item GetParams()
{
   Item p = new Item();
   p.id = parameter.id;
   p.type = parameter.type;
   p.name = parameter.name;
   p.prefab = parameter.prefab;
   p.sprite = parameter.sprite;
   p.atk = parameter.atk;
   p.def = parameter.def;
   p.hp = parameter.hp;
   p.food = parameter.food;
   p.dmg = parameter.dmg;
   p.detail = parameter.detail;
   return p;
}

ついでにInventoryクラスのこの二つのメソッドも変更しておきます。

public Item[] GetAllItem()
{
   Item[] itemList = new Item[items.Count];
   for (int i = 0; i < items.Count; i++)
   {
       Item it = new Item();
       it.id = items[i].id;
       it.type = items[i].type;
       it.name = items[i].name;
       it.prefab = items[i].prefab;
       it.sprite = items[i].sprite;
       it.atk = items[i].atk;
       it.def = items[i].def;
       it.hp = items[i].hp;
       it.food = items[i].food;
       it.dmg = items[i].dmg;
       it.detail = items[i].detail;
       itemList[i] = it;
   }
   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++)
   {
       Item it = new Item();
       it.id = itemList[i].id;
       it.type = itemList[i].type;
       it.name = itemList[i].name;
       it.prefab = itemList[i].prefab;
       it.sprite = itemList[i].sprite;
       it.atk = itemList[i].atk;
       it.def = itemList[i].def;
       it.hp = itemList[i].hp;
       it.food = itemList[i].food;
       it.dmg = itemList[i].dmg;
       it.detail = itemList[i].detail;
       items.Add(it);
   }
   itemNumMax = maxNum;
   this.items = items;
}

次にItemSaveDataクラスに以下のパラメーターを追加します。

public Item parameter;

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

private ItemSaveData[] MakeItemDatas()
{
   int itemCount = items.transform.childCount;
   ItemSaveData[] itemSaveDatas = new ItemSaveData[itemCount];
   for (int i = 0; i < itemCount; i++)
   {
       Transform it = items.transform.GetChild(i);
       ItemMovement move = it.GetComponent<ItemMovement>();
       ItemSaveData itemSaveData = new ItemSaveData();
       itemSaveData.grid = new Pos2D();
       itemSaveData.grid.x = move.grid.x;
       itemSaveData.grid.z = move.grid.z;
       itemSaveData.parameter = it.GetComponent<ItemParamsController>().GetParams();
       itemSaveDatas[i] = itemSaveData;
   }
   return itemSaveDatas;
}

private void LoadItemData(SaveData saveData)
{
   foreach (var data in saveData.itemDatas)
   {
       GameObject itemObj = (GameObject)Resources.Load("Prefabs/" + data.parameter.prefab);
       GameObject it = Instantiate(itemObj, items.transform);
       ItemMovement move = it.GetComponent<ItemMovement>();
       move.SetPosition(data.grid.x, data.grid.z);
       it.GetComponent<ItemParamsController>().SetParams(data.parameter);
   }
}

テストしてみましょう。セーブしてからアイテムを拾い、そのアイテムがフィールド上からなくなった状態でロードします。それで元のアイテムが復活したらOKです。
セーブデータエディターでも確認してみます。

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

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

インベントリの方も地面に落ちているアイテムも全て取得できていますね。

という訳で、今回はここまでにします。
次回はアイテムの詳細表示から始めたいと思っています。

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