RPGゲームのアイテムのデータをJSONファイルで用意

初めまして、新鮮な土筆です。
今回は、[Unity #2 Advent Calendar 2020](https://qiita.com/advent-calendar/2020/unity2)　3日目の記事を書きたいと思います。

#概要
RPGゲームに登場する敵とアイテムのデータをJSONファイルで管理したら、ショップとバトルで必要になるデータが扱いやすいと感じたので、
実際自分がやっているJSONファイルデータの作成方法とその使い方を、ゲームのアイテムデータ作成方法の説明を通して書きたいと思います。

sea_mountain さんの下記の記事を主に参考にしています。ありがとうございました。m(_ _)m
[JsonUtility をつかって Unity で JSON を取り扱う方法](https://qiita.com/sea_mountain/items/6513b330983ffa003959)

##なぜJSONファイルなのか
先にお伝えしたいのですが、私自身プログラムとゲーム作成は始めたばかりの新参ですので、詳しくご説明できません。
実際、ゲームに登場するアイテムのデータを管理する方法は複数あると思います。
ですが、JSONファイルを用いたのには3つの理由があります。

 - JSONファイルを用いると、ScriptableObjectのように1つ1つのデータをエディタ上で別々に開いて編集するのではなく、1つのファイルを開いて個々のアイテムデータを見比べながら編集できる。
 
 - 必要に応じて簡単に値を編集出来るため、アイテムデータに依存するバトルの回復演出等で確認がすぐに出来る。

 
 - JSONファイルはUnityに依存しないので、Unityを触らない人もデータが用意できる(Googleスプレッドシートのほうが…、かもしれません。)

##アイテムデータの用意
下記のJSONファイルでゲームに登場するアイテムの情報をまとめています。
ショップでの買い物のやり取りに必要な情報や、バトルでのアイテム効果の情報をこのファイルから持ってきています。

データの内容は

 - アイテム画像名
 - アイテム名
 - アイテム説明
 - アイテムの種類 (HPやFP回復、攻撃)
 - 量 (回復、攻撃)
 - 購入価格
 - 売却価格　となっています。

```JSON
{
  "gameItems": [
    {
      "imgFileName": "english_muffin",
      "name": "ふつうのパン",
      "description" : "たべたら　元気がでる　パン\nHPが　「５」かいふくする",
      "type": "recoverHp",
      "amount": 5,
      "playersBuyingPrice": 5,
      "playersSellingPrice": 3
    },
    {
      "imgFileName": "food_rice_burger",
      "name": "めちゃうまのパン",
      "description" : "たべたら　かなり元気がでる　パン\nHPが　「１５」かいふくする",
      "type": "recoverHp",
      "amount": 10,
      "playersBuyingPrice": 10,
      "playersSellingPrice": 5
    }
  ]
}

```

Unityのプロジェクト内のResourcesフォルダに JSONフォルダを用意して、アイテムデータのJSONファイルをここにいれておきます。
今回のアイテムデータの名前は"GameItemsData.json"で保存しておきます。

![itemJson.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/608513/a0670eb6-9bb4-8889-d865-406a197ba1a0.png)



##読み込みに必要なクラス

それでは次にJSONファイルの読み込み方法です。
~~上記でご紹介しました　[JsonUtility をつかって Unity で JSON を取り扱う方法](https://qiita.com/sea_mountain/items/6513b330983ffa003959)　の想定するJSONファイルのデータとは異なり、本記事では複数のアイテムデータをまとめた配列を扱います。~~
追記 : 2020/12/06 
上記記事でもint型の配列は取り扱われていらっしゃいますので打ち消し線を加えました。

今回のアイテムデータを読み込むために、クラスを3つ用意します。

 - アイテムの個々の情報をしまうためのクラス

 ```C#
[System.Serializable]
public class Item
{
  public string imgFileName;
  public string name;
  public string description;
  public string type;
  public int amount;
  public int playersBuyingPrice;
  public int playersSellingPrice;
}
 ```

 - アイテムの個々の情報を持つクラスを配列にしまうためのクラス
 
 ```C#
public class ItemDataArray
{
  public Item[] gameItems;
}
 ```


 - JSONファイルのデータを読むための関数を用意するクラス


 ```C#
using UnityEngine;
public class JsonReaderFromResourcesFolder
{
  public ItemDataArray GetItemDataArray ()
  {
    string filePath = "JSON/GameItemsData";
    TextAsset file = Resources.Load (filePath) as TextAsset;
    ItemDataArray items = JsonUtility.FromJson<ItemDataArray> (file.text);
    return items;
  }
}
```
先に3つのクラスをザックリと紹介しました。
これから、3つのクラスの役割を上から順に説明することで、JSONファイルのデータを取り出す方法を説明します。

##アイテムの個々の情報をしまうためのクラス
JSONファイルに記載された個々のアイテムデータは下記の通りでした。

```JSON
{
  "imgFileName": "english_muffin",
  "name": "ふつうのパン",
  "description" : "たべたら　元気がでる　パン\nHPが　「５」かいふくする",
  "type": "recoverHp",
  "amount": 5,
  "playersBuyingPrice": 5,
  "playersSellingPrice": 3
}
```
このデータをゲームで扱うには、それぞれが変数として扱われる際の型を指定する必要があります。
そのために下記のクラスを用意して型を指定しておきます。

 ```C#
[System.Serializable]
public class Item
{
  public string imgFileName;
  public string name;
  public string description;
  public string type;
  public int amount;
  public int playersBuyingPrice;
  public int playersSellingPrice;
}
 ```

この時に [System.Serializable] を書き忘れると、データを変数に代入できませんので注意してください。
また、Itemクラスに記述する変数名はJSONデータのものと同じにしておいてください。
これでアイテムの情報をItemクラスの変数として取り出すクラスが用意できました。

##アイテムの個々の情報を持つクラスを配列にしまうためのクラス
今回は複数のアイテムデータを保持した配列を読み込むため、そのためのクラスが必要です。
JSONファイルのデータは下記のようにアイテムのデータ配列を保持していました。

```JSON
{
  "gameItems": [
    {
      -- 省略 --
    },
    {
      -- 省略 --
    }
  ]
}

```
この"gameItems"を扱うためのクラスを用意します。

 ```C#
public class ItemDataArray
{
  public Item[] gameItems;
}
 ```

上記で用意したItemクラスの配列型のクラスを用意することで、"gameItems"をItem[]で受け取ります。
ここでもクラスの変数名をJSONファイルに合わせてください。異なるとデータが受け取れないので注意です。

 
##JSONファイルのデータを読むための関数を用意するクラス
最後に、JSONファイルを読み込んで上記で用意した2つのクラスに合わせたデータに変換する処理を用意します。
まず下記のようにJSONファイルのデータを読むための関数を持つクラスを用意します。

```C#
using UnityEngine;

public class JsonReaderFromResourcesFolder
{
  public ItemDataArray GetItemDataArray ()
  {
    string filePath = "JSON/GameItemsData";
    TextAsset file = Resources.Load (filePath) as TextAsset;
    ItemDataArray items = JsonUtility.FromJson<ItemDataArray> (file.text);
    return items;
  }
}
```

GetItemDataArray() には、filePath に Resorceフォルダ内のJSONフォルダ以降のパスを使用しています。
今回の場合　"JSON/GameItemsData"　です。

関数内にTextAsset型のfileがありますが、中身はこんな感じで、JSONファイルの中身のまんまです。
![gaemItems.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/608513/289990e8-d0b0-e628-2cdb-5c1b617e78e2.png)


このままのTextAsset型のfileではゲームで扱えず、画像名等の情報が取り出せません。
なので、JsonUtilityを利用して、JSONファイルのデータのgameItems配列を、先に用意したItem型配列であるDataArray型のitemsに変換します。

ここで一度、itemsの変数を確認してみると下記画像のようにgameItemsがとれると思います。
![itemJson8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/608513/68284de8-234b-c275-cee8-c5b7b62d2b95.png)

これでItemDataArray型として、JSONファイルのデータが取れる用意が出来ました。

##アイテムデータが取れていることを確認

最後にアイテムのデータをログで確認します。
![itemJson7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/608513/a1a14d86-b76a-fc73-0b13-1fd078f84696.png)


上記のようにGetItemDataArrayからItemDataArray型の値を受け取ります。
ItemDataArrayはItem型の配列です。試しに一番上に記述していたアイテムの"名前"と"説明"を取得してみます。
![itemJson6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/608513/7efed630-71b0-0995-320d-1d33dd2d5121.png)

これでアイテムのデータがJSONファイルから取れることを確認できました。

至らない点があったかもしれませんが、本記事はこれで以上となります。
どなたかのお役に立てたら幸いです！m(_ _)m

##最後に
自分はパンが好きなのですが、今はやっぱりお米ですよね！
インディーズゲームに幸あれ！