こんにちは、ひっしーです。
今回は、unityでゲーム開発をしている際に外部データ(json)へアクセスしてそのデータから情報を読み取り実際にゲームに反映させる機能を実装したので、その方法について解説いたします。
今回の目次です。
JSONファイルとは、 JavaScript Object Notation の略で簡単に説明するとプログラミングのデータに変換しやすいテキストファイルです。
基本的に取り出したいデータを保存することのみに使われるのでJavaScriptという名前が入っていますが、処理を書くことはできません。
JavaやC#で言うところの変数のみが書かれているファイルになります。
実際には以下の様に記述します。
{
"Name" : "タカシ"
"Hp" : 300,
"Attack" : 15,
"Defense" : 3
}
このように扱いたいデータを{}で囲い、データの名前(キー)と値を:でつなげることでデータを管理することができます。
今回の場合では、”Name”というキーに”タカシ”という値が紐づいており、”Hp”というキーには300という値が紐づいています。
その他も同様の法則で紐づいています。
プログラムの中で扱う際には、このキーを指定することで中の値を取り出すことが可能になります。
では、このJSONファイルをUnityで使用するにはどのように取り扱うのか?
こちらは、 JsonUtility という機能を使用します。
※ (JsonUtility を使用するにはUnityバージョンが 5.3以降である必要があります。
バージョンが年号表記になっているものは5.3以降で間違いないので最近Unityを始めた人などは特に気にする必要はないです。 )
実際に、JsonUtilityの使用方法を解説していきます。
まず初めに、JSONに保存するデータを格納するクラスを作成します。
//C#側のスクリプトで記述
[System.Serializable] //定義したクラスをJSONデータに変換できるようにする
public class PlayerData
{
public string name;
public int hp;
public int attack;
public int defense;
}
通常のクラスと同じように変数を格納するためのクラスを定義します。
一つ違うことは、クラスの上に[System.Serializable]という記述があります。
これは、クラスデータをJSON形式に変換する際に必須の記述になります。
そのため、忘れずにつけるようにしてください。
次に、PlayerDataクラスの中身を決めていきます。
void Start()
{
PlayerData player1 = new PlayerData();
player1.name = "タカシ";
player1.hp = 300;
player1.attack = 15;
player1.defense = 3;
string jsondata = JsonUtility.ToJson(player1); //JSONデータはC#上で文字列として扱う
Debug.Log(jsondata);
}
このスクリプトでは、初めにPlayerData型のPlayer1をインスタンス化しています。
そのあとname,hp,attack,defenseに値をいれています。
値をいれ終えたら、string型で定義したjsondataにJsonUtility.ToJson(player1)としてPlayer1のデータを変換しています。
上記ように記述したスクリプトをUnityのゲームオブジェクトにアタッチして実行するとコンソールに以下のような結果が表示されます。
{"name":"タカシ","hp":300,"attack":15,"defense":3}
初めに説明したJSONファイルの記述と同じ形になっていることがわかります。
JsonUtility を使うことで1行だけでデータをJSON形式に変換することができました。
では、JSON形式のデータをC#のクラスとして読み込む方法を見ていきましょう。
void Start()
{
PlayerData player1 = new PlayerData();
player1.name = "タカシ";
player1.hp = 300;
player1.attack = 15;
player1.defense = 3;
string jsondata = JsonUtility.ToJson(player1);
Debug.Log(jsondata);
//player2を作り、jsondataを読み込む
PlayerData player2 = JsonUtility.FromJson<PlayerData>(jsondata);
Debug.Log("名前:" + player2.name + " HP:" + player2.hp + " Attack:" + player2.attack + " Defense:" + player2.defense);
}
先ほどのスクリプトの下にplayer2を作成し、上で定義していたjsondataの中身をいれています。
JSONデータをPlayerDataの値にするために、JsonUtility.FromJson<変換したい型>(JSONデータ名)を使用しています。
このようにJSONデータを変換したい型と変換するJSONデータを指定することで変換することができます。
実際に実行してみると以下のような結果が出てきます。
名前:タカシ HP:300 Attack:15 Defense:3
Debug.Logの中ですべて表示させているので連なっているように見えますが、一つ一つのデータとして扱われていることがわかるかと思います。
このようにC#上のクラスをJSONに変換、JSONをC#クラスに変換することが容易に行えます。
ここまででは、JSONに変換する意味があまり感じられないと思います。
JSONファイルを使用する最大の目的は、データを保存、読み込みができる点にあります。
では、実際のデータをJSONとして書き出す流れを見てみましょう。
using System.IO;
まず、コードの先頭にusing System.IOを記述することを忘れないでください。
これがないと、ファイルの読み書きができないので必須です。
次にコードを以下の様に書きます。
string datapath;
private void Awake()
{
//初めに保存先を計算する Application.dataPathで今開いているUnityプロジェクトのAssetsフォルダ直下を指定して、後ろに保存名を書く
datapath = Application.dataPath + "/TestJson.json";
}
void Start()
{
PlayerData player1 = new PlayerData();
player1.name = "タカシ";
player1.hp = 350;
player1.attack = 20;
player1.defense = 10;
SaveTest(player1);
}
//セーブのメソッド
public void SaveTest(PlayerData player)
{
string jsonstr = JsonUtility.ToJson(player);//受け取ったPlayerDataをJSONに変換
StreamWriter writer = new StreamWriter(datapath, false);//初めに指定したデータの保存先を開く
writer.WriteLine(jsonstr);//JSONデータを書き込み
writer.Flush();//バッファをクリアする
writer.Close();//ファイルをクローズする
}
こちらは、先頭のdatapathでデータ保存先の指定を保存する変数を定義しています。
その後、Awake(実行すると一番初めに呼ばれる)で datapath の中身が”ユーザー毎/Assets/TestJson.json”になるように指定しています。
Startの中身はほぼ同じで、PlayerDataクラスの中身を指定しています。
違う点としては、最後にSaveTestメソッドを呼んでいます。
では、 SaveTest メソッドの中身ですが、コメントにもあるように受け取ったPlayerDataをJSONに変換して /Assets/TestJson.json に保存してファイルを閉じています。
実際に実行するとunityの Assets フォルダの中に TestJson.json というファイルが保存されているかと思います。
この TestJson.json を開いてみると以下のようなテキストが記述されています。
{"name":"タカシ","hp":350,"attack":20,"defense":10}
これで正しくJsonファイルを出力することができました。
次は出力したJSONファイルを読み込んでみましょう。
以下のようなメソッドを用意します。
public PlayerData LoadTest(string dataPath)
{
StreamReader reader = new StreamReader(dataPath); //受け取ったパスのファイルを読み込む
string datastr = reader.ReadToEnd();//ファイルの中身をすべて読み込む
reader.Close();//ファイルを閉じる
return JsonUtility.FromJson<PlayerData>(datastr);//読み込んだJSONファイルをPlayerData型に変換して返す
}
データパスを受け取ってそのデータパスにあるファイルにアクセスしファイルの中身をPlayerData型として返してくれるメソッドです。
string datapath;
private void Awake()
{
//初めに保存先を計算する
datapath = Application.dataPath + "/TestJson.json";
}
void Start()
{
PlayerData player2 = LoadTest(datapath);
Debug.Log("名前:" + player2.name + " HP:" + player2.hp + " Attack:" + player2.attack + " Defense:" + player2.defense);
}
データを保存したとき同様にデータパスを計算し、パスを変数に格納します。
次に、PlayerData型のplayer2を指定して、中身をLoadTestで返ってきた値にしています。
最後にコンソールに表示するためDebug.Logで値を表示させています。
こちらを実行すると以下のような結果が出ます。
名前:タカシ HP:350 Attack:20 Defense:10
保存した値になっていそうですね。
このようにJSONファイルに保存と読み込みを使うことで様々なセーブ機能を実装することが可能になります。
以下、要点のまとめになります。
今回は、UnityでJSONファイルを扱う方法について解説しました。
UnityからJSONファイルを扱う方法は、言葉の響きほど難しくないことが分かったかと思います。
JSONファイルを使用することでデータの保存やデータの呼び出しが容易にできるようになるので、セーブ機能やロード機能が実装できるようになります。
RPGなどでは欠かせない機能になりますので皆さんもぜひ使用してみてください。