[Unity][C#] XMLファイルとしてデータを保存する
ゲームで使用しているオブジェクトのデータをファイルに保存する方法のメモ書きです。
ファイルに保存する方法はいろいろありますが、C#に備わっているシリアライズ/デシリアライズの機能を用いると便利です。
.NET FrameworkにてXMLとしてシリアライズ/デシリアライズできるXmlSerializerクラスが用意されています。
今回はこれを用いてゲームデータの保存・読み出しを行ってみたいと思います。
シリアライズ/デシリアライズ
XmlSerializerを用いてシリアライズ/デシリアライズする処理は以下のようになります。
using System.IO; using System.Xml; using System.Xml.Serialization; public class XmlUtil { // シリアライズ public static T Seialize<T>(string filename, T data) { using ( var stream = new FileStream(filename, FileMode.Create) ) { var serializer = new XmlSerializer(typeof(T)); serializer.Serialize(stream, data); } return data; } // デシリアライズ public static T Deserialize<T>(string filename) { using ( var stream = new FileStream(filename, FileMode.Open) ) { var serializer = new XmlSerializer(typeof(T)); return (T)serializer.Deserialize(stream); } } }
XmlSerializerはnewでインスタンス化することで使えるようになります。
var serializer = new XmlSerializer(typeof(T));
XMLへのシリアライズはXmlSerializer.Serialize()により行います。
serializer.Serialize(stream, data);
第1引数にシリアライズされたXMLデータを出力するストリーム、第2引数にシリアライズするデータを指定します。
ここで、dataのデータ型はシリアライズ可能な型でなければなりません。
構造体やArray、Listなどはシリアライズできますが、Dictionaryはシリアライズできません。
デシリアライズはXmlSerializer.Deserialize()により行います。
(T)serializer.Deserialize(stream);
引数にはシリアライズされたXMLデータを受け取るストリームを指定します。
このメソッドを実行するとデシリアライズされたデータが返却されます。
使ってみる
実際にXMLにゲームデータを保存してみましょう。
構造体変数のデータをシリアライズ/デシリアライズする処理は以下のようになります。
using UnityEngine; using System.Collections; using System.Collections.Generic; public class SerializeTest : MonoBehaviour { // テスト用のシリアライズデータフォーマット [System.Serializable] public struct TestData { public string playerName; public Vector3 playerPos; public Vector3[] shotPos; public List<Vector3> enemyPos; }; public TestData testData; // シリアライズ/デシリアライズするデータ private string serializeDataPath; // シリアライズされるファイル名 // テストデータ初期化 void Start() { serializeDataPath = Application.dataPath + "/SerializeData.xml"; // 適当なデータを作成 testData = new TestData() { playerName = "Player1", playerPos = new Vector3(Random.value, Random.value, Random.value), shotPos = new Vector3[] { new Vector3(Random.value, Random.value, Random.value), new Vector3(Random.value, Random.value, Random.value), new Vector3(Random.value, Random.value, Random.value), }, enemyPos = new List<Vector3>() { new Vector3(Random.value, Random.value, Random.value), new Vector3(Random.value, Random.value, Random.value), }, }; } // シリアライズ・デシリアライズ void Update() { if ( Input.GetKeyDown(KeyCode.S) ) { XmlUtil.Seialize<TestData>(serializeDataPath, testData); } if ( Input.GetKeyDown(KeyCode.D) ) { testData = XmlUtil.Deserialize<TestData>(serializeDataPath); } } }
Sキーでシリアライズ、Dキーでデシリアライズします。
シリアライズしたデータを開いてみると、以下のようにきちんとXML形式でデータが保存されていることが確認できます。
<?xml version="1.0" encoding="shift_jis"?> <TestData xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <playerName>Player1</playerName> <playerPos> <x>0.658014953</x> <y>0.884079933</y> <z>0.8437089</z> </playerPos> <shotPos> <Vector3> <x>0.542741358</x> <y>0.171121612</y> <z>0.112001911</z> </Vector3> <Vector3> <x>0.215804726</x> <y>0.168900743</y> <z>0.9638424</z> </Vector3> <Vector3> <x>0.9928707</x> <y>0.004624248</y> <z>0.009210945</z> </Vector3> </shotPos> <enemyPos> <Vector3> <x>0.660212934</x> <y>0.682383239</y> <z>0.561078</z> </Vector3> <Vector3> <x>0.820451</x> <y>0.0625197962</y> <z>0.9366993</z> </Vector3> </enemyPos> </TestData>
あらゆる型の変数に対応しているため、簡単なファイル保存用途にはこの方法で十分対応できるでしょう。