ゲームデータについて(9)ジェネリックの利用
これまで紹介したサンプルプログラムは固定データ・可変データを1種類ずつしか持っていませんが、大抵のゲームでは多数用意することになると思います。 今のままでは各クラス間で重複するコードが多く、データの種類が追加される度にこれらを全て書く必要があります。 C#のジェネリック(C++のテンプレート)を利用することでコード量の削減が見込めます。
固定データクラスのジェネリック化
Assets/GameData/FixedData/FixedDataManager.csを修正
using UnityEngine; using UnityEngine.Assertions; using System; //この行を追加. using System.Collections.Generic; using System.Runtime.Serialization.Formatters.Binary; using System.IO; public static class FixedDataManager { // ここからを追加. [Serializable] public class FixedDataList<T> where T : class { private List<T> _list = new List<T>(); public List<T> list { get { return _list; } } public int GetDataCount() { return list.Count; } public bool CheckValidIndex(int index) { return (index >= 0) && (index < GetDataCount()); } public T GetData(int index) { if (!CheckValidIndex(index)) { Assert.IsTrue(false); return null; } return list[index]; } public void Add(T data) { list.Add(data); } } private static FixedDataList<FixedMonsterData> _monsterList = null; public static FixedDataList<FixedMonsterData> monsterList { get { return _monsterList; } } // ここまでを追加. // ここからを削除. //private static List<FixedMonsterData> _monsterList = null; //public static List<FixedMonsterData> monsterList //{ // get { return _monsterList; } //} // ここまでを削除. (中略) private static void Initialize() { // この行を下の行に差し替え. //_monsterList = new List<FixedMonsterData>(); _monsterList = new FixedDataList<FixedMonsterData>(); } (中略) public static void Serialize() { // この行を下の行に差し替え. //_monsterList = ReadSerializedData<List<FixedMonsterData>>("FixedData/FixedMonsterData"); _monsterList = ReadSerializedData<FixedDataList<FixedMonsterData>>("FixedData/FixedMonsterData"); } // ここからを削除. //public static int GetMonsterDataCount() //{ // return _monsterList.Count; //} //public static bool CheckValidMonsterIndex(int index) //{ // return (index >= 0) && (index < GetMonsterDataCount()); //} //public static FixedMonsterData GetMonsterData(int index) //{ // if (!CheckValidMonsterIndex(index)) // { // Assert.IsTrue(false); // return null; // } // return _monsterList[index]; //} // ここまでを削除. }
Assets/Editor/FixedDataConverter.csを修正
// この行を下の行に差し替え. //List<FixedMonsterData> monsterList = FixedDataManager.monsterList; FixedDataManager.FixedDataList<FixedMonsterData> monsterList = FixedDataManager.monsterList;
Assets/GameData/TextData/TextDataManager.csを修正
// モンスター名. case REPLACE_TYPE.MONSTER: { if (counter >= replaceMonsterParams.Count) { Assert.IsTrue(false); break; } int id = replaceMonsterParams[counter]; // この行を下の行に差し替え. //strAdd = FixedDataManager.GetMonsterData(id).GetName(); strAdd = FixedDataManager.monsterList.GetData(id).GetName(); } break;
可変データクラスのジェネリック化
VariableDataManagerクラスのGetCharacterDataFormID(int)関数はCharacterDataクラスのメンバint _id
を参照しています。
public static CharacterData GetCharacterDataFormID(int id) { if (id < 0) { Assert.IsTrue(false); return null; } CharacterData characterData = characterList.Find(x => x.id == id); // ここでメンバ_idを参照. if (characterData == null) { Assert.IsTrue(false); return null; } return characterData; }
このままではジェネリックを利用できないので、可変データのベースクラスとしてメンバint id
のみを持つBaseVariableDataクラスを作成し、ジェネリック型制約(where句)を利用して実装、CharacterDataはBaseVariableDataの派生という形にします。
Assets/GameData/VariableData/BaseVariableData.csを作成
using System; [Serializable] public class BaseVariableData { private int _id = -1; public int id { get { return _id; } set { _id = value; } } public void Init(int _id) { id = _id; } public void Clear() { id = -1; } public void Copy(BaseVariableData data) { id = data.id; } public bool IsValid() { return id != -1; } }
Assets/GameData/VariableData/CharacterData.csを修正
using System; [Serializable] // ここからを削除. //public class CharacterData //{ // private int _id = -1; // public int id // { // get { return _id; } // set { _id = value; } // } // ここまでを削除. // ここからを追加. public class CharacterData : BaseVariableData { // ここまでを追加. (中略) public void Init( int _id, int _level, int _hp, int _mp, int _attack, int _defense, int _agility ) { // この行を下の行に差し替え. //id = _id; base.Init(_id); level = _level; hp = _hp; mp = _mp; attack = _attack; defense = _defense; agility = _agility; } // ここからを削除. //public void Clear() //{ // id = -1; // ここまでを削除. // ここからを追加. new public void Clear() { base.Clear(); // ここまでを追加. level = 0; hp = 0; mp = 0; attack = 0; defense = 0; agility = 0; } public void Copy( CharacterData data ) { // この行を下の行に差し替え. //id = data.id; base.Copy(data); level = data.level; hp = data.hp; mp = data.mp; attack = data.attack; defense = data.defense; agility = data.agility; } // ここからを削除. //public bool IsValid() //{ // return id != -1; //} // ここまでを削除. // ここからを追加. new public bool IsValid() { return base.IsValid(); } // ここまでを追加.
Assets/GameData/VariableData/VariableDataManager.csの修正
using System; // この行を追加. using System.Collections.Generic; using System.IO; using System.Runtime.Serialization.Formatters.Binary; using UnityEngine.Assertions; public static class VariableDataManager { // ここからを追加. [Serializable] public class VariableDataList<T> where T : BaseVariableData { private List<T> _list = new List<T>(); private List<T> list { get { return _list; } set { _list = value; } } public void Add(T data) { list.Add(data); } public void Clear() { list.Clear(); } public T GetData(int index) { if (index < 0 || index >= list.Count) { Assert.IsTrue(false); return null; } return list[index]; } public T GetDataFromID(int id) { if (id < 0) { Assert.IsTrue(false); return null; } T data = list.Find(x => x.id == id); if (data == null) { Assert.IsTrue(false); return null; } return data; } public int GetDataCount() { return list.Count; } } private static VariableDataList<CharacterData> _characterList = null; public static VariableDataList<CharacterData> characterList { get { return _characterList; } set { _characterList = value; } } // ここまでを追加. // ここからを削除. //private static List<CharacterData> _characterList = null; //private static List<CharacterData> characterList //{ // get { return _characterList; } // set { _characterList = value; } //} (中略) private static void Initialize() { // この行を下の行に差し替え. //characterList = new List<CharacterData>(); characterList = new VariableDataList<CharacterData>(); } (中略) public static void LoadData(FileStream fileStream) { BinaryFormatter binaryFormatter = new BinaryFormatter(); // この行を下の行に差し替え. //characterList = binaryFormatter.Deserialize(fileStream) as List<CharacterData>; characterList = binaryFormatter.Deserialize(fileStream) as VariableDataList<CharacterData>; } // ここからを削除. //public static CharacterData GetCharacterData(int index) //{ // if (index < 0 || index >= characterList.Count) // { // Assert.IsTrue(false); // return null; // } // // return characterList[index]; //} //public static CharacterData GetCharacterDataFormID(int id) //{ // if (id < 0) // { // Assert.IsTrue(false); // return null; // } // // CharacterData characterData = characterList.Find(x => x.id == id); // if (characterData == null) // { // Assert.IsTrue(false); // return null; // } // // return characterData; //} //public static int GetCharacterDataNum() //{ // return characterList.Count; //} // ここまでを削除.