동물의 능력에 관한 시트이다.
이런 시트에서 한 행을 클래스 인스턴스화 하는 것과 전체를 리스트화하는 것을 알아볼 것이다.
1. 스프레드 시트 -> 텍스트 데이터
스프레드 시트를 텍스터 데이터화하려면 특수한 링크가 필요하다.
기존 스프레드 시트의 링크는 이렇다.
여기서 tsv 데이터(탭으로 나눠져 있는 텍스트 데이터)로 바꾸기 위해서는...
{Address}/export?format=tsv&range={Range}&gid={SheetID}
이런 꼴로 고쳐주어야 하는데,
1. Address
위에 나와있는 링크의 /edit 전 까지의 부분이다.
2. Range
이 노란 부분 {A2:D7}이 Range이다. 우리는 더 많은 데이터가 추가될 수 있으므로 {A2:D} 영역을 선택할 것이다.
3. Sheet ID
스프레드 시트에서 여러 시트를 만들면, 시트마다 다르다. 시트를 식별하는 고유 번호이다.
즉,
https://docs.google.com/spreadsheets/d/1AG7XW-6r4R6yC33K1mVNCb4HWHe-bgtjbCOTtAn97DU/export?format=tsv&range=A2:D&gid=1191946581
이렇게 만들면 데이터가 불러와진다.
이런 식으로.
하지만... 시트마다 이 짓을 할 수 없기 때문에 이 주소를 반환하는 간단한 함수를 만들겠다.
그러면, UnityWebRequest와 코루틴으로 tsv를 가져와서 디버그 로그창에 찍어볼 것이다.
코루틴으로 UnityWebRequest가 데이터를 읽어올 때까지 기다리는 코루틴이다.
유니티의 빈 오브젝트에 넣어 실행해보겠다.
실행하기 전 액세스 권한을 링크가 있는 모든 사용자로 바꿔주어야 한다.
잘 나온 것을 볼 수 있다 ^__^
2. 클래스 인스턴스화
Animal이라는 클래스에 동물의 이름, 공격력, 방어력, 타입을 넣어줄 것이다. C# 리플렉션 개념이 나오니 나도 집중해야 한다...
데이터를 담을 클래스 코드를 짜준다!
주의할 점
1. 시트에 있는 데이터와 순서가 일치해야 한다.
2. Enum값은 시트에 나와있는 데이터와 이름이 완전히 똑같아야 한다.
> 예를 들어 pink나 PINK는 안된다
그럼 클래스화하는 코드를 짜겠다.
T GetData<T>(string[] datas)
{
object data = Activator.CreateInstance(typeof(T));
// 클래스에 있는 변수들을 순서대로 저장한 배열
FieldInfo[] fields = typeof(T).GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
for (int i = 0; i < column.Length; i++)
{
try
{
// string > parse
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;
}
너무 길어서 코드블록으로 뺐다.
테스트를 해볼 것이다.
잘 나오는 것을 볼 수 있다.
2. 클래스 리스트화
사실, 인스턴스화를 했으면 리스트화하는 것은 그렇게 어렵지 않다. 개행으로 나누고, 탭으로 나눈 배열을 GetData의 인자로 던져주고, 그것을 차곡차곡 리스트에 모으면 되기 때문이다.
잘 들어오는 것을 볼 수 있다.
3. 자식 클래스 인스턴스
그런데 만약 Animal을 상속받은 Rabbit, Tiger 클래스가 있는 리스트를 반환받고 싶으면 어떡하지?
Activator을 사용해서 CreateInstance를 하고 있으므로, 클래스의 이름(string)만 있다면 충분히 구현할 수 있다.
자식 인스턴스를 가지고 있는 리스트를 반환하는 함수를 만들어준다.
주의할 점: 해당 코드에서는 클래스의 이름이 0번째에 없다면 작동하지 않는다!!
GetData 함수 상단도 조금 바꿔 준다.
string으로 클래스의 이름을 받고 해당 클래스가 있다면 자식으로 생성을, 없다면 T형(부모)으로 인스턴스를 생성한다.
테스트용으로 Animal 클래스에 가상 함수를 만들고,
Rabbit과 Tiger 클래스 또한 만들어주었다. 둘은 부모의 함수를 재정의한다.
테스트 코드를 써봤다.
돌려보면...
만들어준 Rabbit클래스와 Tiger 클래스가 잘 생성되는 것을 볼 수 있다!!
4. 타입에 따라 분류
다른 스크립트들도 쓸 수 있게 타입에 따라 Dictionary로 분류했다.
길었던 스프레드 시트 로드의 끝이다.
나는 고등학생이고 아직 배우는 중이라 조금 부족할 수도 있지만, 혹여 필요한 분들을 위해 깃허브 링크를 공유한다.
Activator에 대해서도 조만간 심도 있게 공부를 해야겠다.
'Unity' 카테고리의 다른 글
[Unity][최적화] 졸업작품 빌드 용량 줄이기 (0) | 2023.05.21 |
---|---|
[Unity] Scriptable Object를 JSON으로 저장할 때의 문제점 (0) | 2022.12.26 |
[Unity][C#] 모두의 마블 게이지 만들기 (1) | 2022.11.13 |