[System.Serializable]
public class EnemyStatus
{
public string name;
public MonsterType monsterType;
public int health;
public int attack;
public float attackSpeed;
public float attackRange;
public AttackType attacType;
public float moveSpeed;
public int soul;
public int exp;
}
public enum AttackType
{
Melee,
Ranged,
Dual
}
public enum MonsterType
{
Normal,
Rare,
Named,
Boss
}
직렬화로 System.Serializable을 추가하여 생성한다.
public List<EnemyStatus> enemys;
private Dictionary<Type, string> sheetDatas = new Dictionary<Type, string>();
public void Awake()
{
sheetDatas.Add(typeof(EnemyStatus), GetCSVAddress(adress, range, sheetID));
}
enemys라는 변수에 각 Enemy의 정보를 저장한 List 변수를 선언하고 시트에서 불러올 주소인 딕셔너리 변수에 클래스변수 Type과 주소인 string으로 선언한다.
public IEnumerator LoadData()
{
List<Type> sheetTypes = new List<Type>(sheetDatas.Keys);
foreach (Type type in sheetTypes)
{
UnityWebRequest www = UnityWebRequest.Get(sheetDatas[type]);
yield return www.SendWebRequest();
// 딕셔너리의 value 값 변경
sheetDatas[type] = www.downloadHandler.text;
if (type == typeof(EnemyStatus))
{
enemys = GetDatasAsChildren<EnemyStatus>(sheetDatas[type]);
foreach (EnemyStatus enemyStatus in enemys)
{
// 저장된 enemy 정보들 처리
}
}
}
}
원래 value값이 주소였는데 가져온 텍스트의 정보로 value값을 변경해준다.
위의 사진 처럼 열을 나누는 \t와 행을 나누는 \n으로 잘라서 string[]변수인 datas에 추가
List<T> GetDatasAsChildren<T>(string data)
{
List<T> dataList = new List<T>();
// 셀의 행의 값을 배열에 저장 (농부, 냥꾼 등 각 내용을 배열에 저장한다는 뜻)
string[] splitedData = data.Split('\n');
// 저장한 배열의 값에 접근
foreach (string element in splitedData)
{
// 해당 객체의 정보를 배열에 저장(농부의 체력, 공격력 등 내용을 배열에 저장)
string[] datas = element.Split('\t');
dataList.Add(GetData<T>(datas, datas[0]));
}
return dataList;
}
FieldInfo[] fields = typeof(T).GetFields()는 제네릭 T에 있는 필드들의 정보를 가져오는 것인데 순서대로 필드를 가져오기 때문에 시트의 내용과 T에 넣을 클래스의 순서가 맞아야한다.
1. BindingFlags.Public: public인 필드
2. BindingFlags.NonPublic: public을 제외한 필드
3. BindingFlags.Instance: 필드에 있는 instance
4. BindingFlags.static: 필드에 있는 static
T GetData<T>(string[] datas, string typeName = "")
{
object data;
// childType이 비어있거나 그런 Type이 없을 때
if (string.IsNullOrEmpty(typeName) || Type.GetType(typeName) == null)
{
data = Activator.CreateInstance(typeof(T));
}
else
{
data = Activator.CreateInstance(Type.GetType(typeName));
}
// 클래스에 있는 변수들을 순서대로 저장한 배열 (순서대로 진행이 되므로 스프레드시트와 클래스의 순서가 같아야함)
FieldInfo[] fields = typeof(T).GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
for (int i = 0; i < datas.Length; i++)
{
// 필드의 내용을 인스턴스 data에 저장
try
{
// string > parse
// EnemyStatus에 선언한 변수들의 순서대로 타입을 확인
Type type = fields[i].FieldType;
if (string.IsNullOrEmpty(datas[i])) continue;
if (type == typeof(int))
fields[i].SetValue(data, int.Parse(datas[i]));
else if (type == typeof(float))
fields[i].SetValue(data, float.Parse(datas[i]));
else if (type == typeof(bool))
fields[i].SetValue(data, bool.Parse(datas[i]));
else if (type == typeof(string))
fields[i].SetValue(data, datas[i]);
// enum
else
fields[i].SetValue(data, Enum.Parse(type, datas[i]));
}
catch (Exception e)
{
Debug.LogError($"SpreadSheet Error : {e.Message}");
}
}
return (T)data;
}
필드의 내용을 순서대로 받아서 타입을 확인하여 타입을 SetValue로 변경을 하여 모든 필드의 타입을 변경해주고 반환을 합니다.
if (type == typeof(EnemyStatus))
{
enemys = GetDatasAsChildren<EnemyStatus>(sheetDatas[type]);
foreach (EnemyStatus enemyStatus in enemys)
{
// 저장된 enemy 정보들 처리
}
}
이제 정보를 foreach로 각 정보를 enemyStatus에 넣어서 각 정보를 처리를 한다.
1.
1. 없음
1. 없음