목차

반응형

목차

1. 원리 파악하기

1.1 검색 조건 정의

1.2 엑셀 데이터를 행 단위로 쪼개기

 

1.3 행 단위로 쪼갠 데이터를 열 단위로 다시 쪼개기

 

2. 데이터 매칭을 위한 키

 

 

 

 

 

1. 원리 파악하기

지난번 강좌에서 TestData로 데이터를 불러오는 부분에 대해서 설명을 하고자 한다.

해당 설명을 들어가기 전에 앞서 스크립터블 오브젝트라는 것에 대한 이해를 하고 있어야 한다.

스크립터블 오브젝트는 추후에 설명하는 글을 써야겠다. 일단은 모른다면 친절한 글이 많으니까 이해하고 오도록 하자

 

TestData라는 오브젝트의 스크립트를 열어보면 크게 두 부분으로 나뉜다.

 

테스트 데이터 객체에 대한 정의

public class TestData : ScriptableObject
{
    public string associatedSheet = "";
    public string associatedWorksheet = "";

    public List<string> items = new List<string>();
    
    public List<string> Names = new List<string>();
    
    //1.3 긁어온 행 데이터를 조회하는 부분
    internal void UpdateStats(List<GSTU_Cell> list, string name)
    {
        items.Clear();
        int math=0, korean=0, english=0;
        for (int i = 0; i < list.Count; i++)
        {
            switch (list[i].columnId)
            {
                case "Math":
                {
                    math = int.Parse(list[i].value);
                    break;
                }
                case "Korean":
                {
                    korean = int.Parse(list[i].value);
                    break;
                }
                case "English":
                {
                    english = int.Parse(list[i].value);
                    break;
                }
            }
        }
        Debug.Log($"{name}의 점수 수학:{math} 국어:{korean} 영어:{english}");
    }

}

 

생성된 테스트 객체의 커스텀 에디터(스크립터블 오브젝트의 인스펙터 부분이라고 생각하면 된다.)

[CustomEditor(typeof(TestData))]
public class DataEditor : Editor
{
    TestData data;

    void OnEnable()
    {
        data = (TestData)target;
    }

    public override void OnInspectorGUI()
    {
        base.OnInspectorGUI();

        GUILayout.Label("Read Data Examples");

        if (GUILayout.Button("Pull Data Method One"))
        {
            UpdateStats(UpdateMethodOne);
        }
    }

//1.1 GSTU_Search 객체를 생성하는 부분
    void UpdateStats(UnityAction<GstuSpreadSheet> callback, bool mergedCells = false)
    {
        SpreadsheetManager.Read(new GSTU_Search(data.associatedSheet, data.associatedWorksheet), callback, mergedCells);
    }

    void UpdateMethodOne(GstuSpreadSheet ss)
    {
        //1.2 행 데이터를 긁어오기
        foreach (string dataName in data.Names)
            data.UpdateStats(ss.rows[dataName], dataName);
        EditorUtility.SetDirty(target);
    }
    
}

 

 

DataEditor부분에서 생성된 Pull Data Method One 버튼을 클릭하면 TestData의 UpdateMethodOne을 호출한다고 생각하면된다.(정확히는 TestDataEditor의 UpdateStats 함수를 호출하고 결과 콜백을 TestData의 UpdateMethodOne으로 넘겨준다가 맞다. 해당 강좌의 주제는 엑셀이라서 이런 건 몰라도 크게 상관없다.)

 

중점적으로 봐야 하는 부분은 세 곳이다.

 

1.1 검색 조건 정의

void UpdateStats(UnityAction<GstuSpreadSheet> callback, bool mergedCells = false)
{
	SpreadsheetManager.Read(new GSTU_Search(data.associatedSheet, data.associatedWorksheet), callback, mergedCells);
}

여기서 new GSTU_Search로 GSTU_Search 객체를 생성하는 부분이 매우 중요하다.

데이터 검색을 하기 전에 조건을 설정하는 부분이다.

 

GSTU_Search 클래스의 정의를 보자.

public class GSTU_Search
    {
        public readonly string sheetId = "";
        public readonly string worksheetName = "Sheet1";

        public readonly string startCell = "A1";
        public readonly string endCell = "Z100";

        public readonly string titleColumn = "A";
        public readonly int titleRow = 1;

        public GSTU_Search(string sheetId, string worksheetName)
        {
            this.sheetId = sheetId;
            this.worksheetName = worksheetName;
        }

        public GSTU_Search(string sheetId, string worksheetName, string startCell)
        {
            this.sheetId = sheetId;
            this.worksheetName = worksheetName;
            this.startCell = startCell;
        }

        public GSTU_Search(string sheetId, string worksheetName, string startCell, string endCell)
        {
            this.sheetId = sheetId;
            this.worksheetName = worksheetName;
            this.startCell = startCell;
            this.endCell = endCell;
        }

        public GSTU_Search(string sheetId, string worksheetName, string startCell, string endCell, string titleColumn, int titleRow)
        {
            this.sheetId = sheetId;
            this.worksheetName = worksheetName;
            this.startCell = startCell;
            this.endCell = endCell;
            this.titleColumn = titleColumn;
            this.titleRow = titleRow;
        }
    }

 

 

다양한 형태의 GSTU_Search 생성자가 있는데 검색 시작 셀을 지정하고 워크시트의 이름을 정하는 등 다양한 기능을 내포하고 있다.

가장 기본 형태의 GSTU_Search를 생성하였기 때문에 Sheet1 이름을 가진 시트의 A1 셀부터 Z100셀까지 쭈욱 긁어오는 기본적인 검색을 하는 것이다.

일단 검색을 하려면 검색 객체를 만들어야 한다는 것만 알아두고 넘어가자 계속 설명할 것이다.

 

1.2 엑셀 데이터를 행 단위로 쪼개기

데이터를 불러왔으면 데이터의 행단 위로 쪼개서 분석을 해야 한다.

 

void UpdateMethodOne(GstuSpreadSheet ss)
    {
        //data.UpdateStats(ss.rows["Jim"]);
        foreach (string dataName in data.Names)
            data.UpdateStats(ss.rows[dataName], dataName);
        EditorUtility.SetDirty(target);
    }

data.Names에는 Jim, Jay, Jack이라는 행 데이터의 키 역할을 하는 값들이 들어있어서 ss.rows[dataName] 을 통해 행중에서 Jim, Jay, Jack 즉 3 개행의 데이터를 뽑아낸 것이다.

 

1.3 행 단위로 쪼갠 데이터를 열 단위로 다시 쪼개기

뽑아낸 행 데이터를 다시 열 단위로 쪼개서 조회해야 한다.

열 단위 데이터 조회하는 부분은 총 세 가지의 샘플 코드가 있다.

세 가지 형태의 샘플 코드를 한번 봐보자.

//1번 방식
internal void UpdateStats(List<GSTU_Cell> list)
    {
        items.Clear();

        for (int i = 0; i < list.Count; i++)
        {
            switch (list[i].columnId)
            {
                case "Health":
                    {
                        health = int.Parse(list[i].value);
                        break;
                    }
                case "Attack":
                    {
                        attack = int.Parse(list[i].value);
                        break;
                    }
                case "Defence":
                    {
                        defence = int.Parse(list[i].value);
                        break;
                    }
                case "Items":
                    {
                        items.Add(list[i].value.ToString());
                        break;
                    }
            }
        }
    }

//2번 방식
    internal void UpdateStats(GstuSpreadSheet ss)
    {
        items.Clear();
        health = int.Parse(ss[name, "Health"].value);
        attack = int.Parse(ss[name, "Attack"].value);
        defence = int.Parse(ss[name, "Defence"].value);
        items.Add(ss[name, "Items"].value.ToString());
    }

//3번 방식
    internal void UpdateStats(GstuSpreadSheet ss, bool mergedCells)
    {
        items.Clear();
        health = int.Parse(ss[name, "Health"].value);
        attack = int.Parse(ss[name, "Attack"].value);
        defence = int.Parse(ss[name, "Defence"].value);

        //I know that my items column may contain multiple values so we run a for loop to ensure they are all added
        foreach (var value in ss[name, "Items", true])
        {
            items.Add(value.value.ToString());
        }
    }

방법은 다르지만 결국은 똑같은 시트의 Health, Attack, Defence, Items를 긁어오는 것이다.

그냥 이중에 하나만 잘 써도 충분하다. 나는 사실 첫 번째 방법만 계속 써서 다른 두 가지 방법이 있는지 몰랐을 정도로 잘 썼다.

 

internal void UpdateStats(List<GSTU_Cell> list, string name)
    {
        items.Clear();
        int math=0, korean=0, english=0;
        for (int i = 0; i < list.Count; i++)
        {
            switch (list[i].columnId)
            {
                case "Math":
                {
                    math = int.Parse(list[i].value);
                    break;
                }
                case "Korean":
                {
                    korean = int.Parse(list[i].value);
                    break;
                }
                case "English":
                {
                    english = int.Parse(list[i].value);
                    break;
                }
            }
        }
        Debug.Log($"{name}의 점수 수학:{math} 국어:{korean} 영어:{english}");
    }

위의 코드는 첫 번째 방법을 조금 변형한 것이다.

행 단위 데이터를 이루고 있는 열 단위의 데이터 중에서 switch문을 통하여 칼럼 값이 내가 필요한 Math, Korean, English 부분만을 긁어오는 것이다.

 

 

2. 데이터 매칭을 위한 키

이쯤에서 데이터 매칭을 위한 키가 필요하다는 부분을 한번 짚고 넘어가도록 하겠다.

 

당신이 엑셀 아래와 같은 데이터 시트가 있다고 하자.

 

  체력 공격력 방어력
원숭이 99 9 9
군인 99 10 10
고릴라 9999 9999 9999

위 시트의 데이터를 긁어오는 것은 어렵지 않다 충분히 구현할 수 있다.

문제는 캐릭터를 생성할 때마다 시트를 긁어와서 넣어주면 너무 비효율적이기 때문에 한번 긁어와 놓고 어딘가에 저 데이터를 저장해놓고 사용해야 한다는 점이다.

어떻게 할 것인가? 한번 고민해보도록 하자.

우리 강의는 시청자가 고민할 시간을 제공한다.

 

 

 

 

 

 

 

 

 

 

 

 

 

바로 스크롤을 슉슉 내렸는가 사실 나라도 그랬을 것 같다.

여하튼 나의 경우에는 스크립터블 오브젝트를 만들어놓고 해당 스크립터블 오브젝트에 엑셀에서 긁어온 값들을 넣어놓고 사용한다. 그리고 그 스크립터블 오브젝트를 전부 다 들고 있고 관리하는 로컬 데이터베이스 클래스가 있다.

요 구조에 대해서는 나중에 또 실습을 해볼 것이다.

그전에 지금 얘기하고 있는 중요한 부분 데이터 매칭을 위한 키를 정해야 한다는 점에 대해서 얘기하겠다.

 

엑셀에서 데이터를 긁어왔는데 긁어온 데이터는 스스로 목적지를 찾아서 들어가 주지 않는다.

즉 유니티 내부에서 저장해놓을 곳과 엑셀 데이터의 매칭을 위한 약속을 해야 한다는 것이다.

이 부분을 깔끔하게 정하지 않으면 더러운 하드코딩으로 악순환이 돼버릴 수 있다.

 

기본적으로는 절대로 변하지 않는 데이터에 대한 키 값을 정해야 한다.(또한 키가 키 외에 다른 역할을 하지 않도록 하자)

아래 표를 보면 원숭이, 군인, 고릴라는 키 역할을 하면서 동시에 게임 내부에서 오브젝트 명까지 맡고 있다. 충분히 바뀌지 않을 수 있지만 오브젝트 명은 언제든지 바뀔 수 있다. 그렇기 때문에 분리를 해야 한다.

  체력 공격력 방어력
원숭이 99 9 9
군인 99 10 10
고릴라 9999 9999 9999

  이름 체력 공격력 방어력
char_monkey 숭숭이 99 9 9
char_solider 군인 99 10 10
char_gorilla 고륄라 9999 9999 9999
  이름 체력 공격력 방어력
001 숭숭이 99 9 9
002 군인 99 10 10
003 고륄라 9999 9999 9999

이런식으로 분리를 하자는 것이다. 기왕이면 키만 봐도 어떤 데이터인지 알 수 있는 char_monkey 형태가 좋은 것 같다. 나는 001 형식으로 인덱스 값을 부여해서 사용하는데 문제는 딱히 없다.

 

 

유니티 구글 스프레드 시트 연동 - 설정

유니티 구글 스프레드 시트 연동 - 원리 파악

 

반응형