본문 바로가기

유니티 스파르타 캠프 7주차

250522 유니티로 쉽게 데이터 관리하는 방법

뭔가 최근 들어 강의를 계속 듣는 거 같습니다. 

오늘은 김휘 튜터님께서 실무에서 엑셀, CSV를 통해서 데이터를 작성하고 유니티에서 불러와 사용하는 방식을 보여주셨습니다.

코드를 좀 더 자세히 볼 수 있었으면 활용하는 방식을 바로 작성하고 끝낼 수 있었겠지만, 방식에 대해서만 알려주시고

CSV를 괜히 사용하려고 다른 것을 등한시할까봐 알려주시지는 않았습니다.


허나..

방법에 대해 배웠음에도 그 내용을 자세히 알지 못하고, 활용을 이해하지 못한다면 저는 그것을 모르는 것과 다름없다고 생각합니다. 그래서 관련 자료로 내용을 정리만 해놓고 튜터님 말처럼 넘어가보도록 하겠습니다.

https://dongsik-blog.tistory.com/101

 

Unity에서 엑셀파일, csv파일 데이터 읽기(겁나 상세하게 적음)

저 엑셀파일 저장하는거 부터 한글 다 깨지고... 첫 도전은 오래 걸리고 낯설고 힘들지만 그 과정에서 인내를 얻고 끝에는 뿌듯함과 앞으로도 할 수 있을거란 자신감을 갖게 되는 거 같습니다.

dongsik-blog.tistory.com

 

https://fkdl0048.github.io/unity/unity_in_CSV/

 

[Unity] CSV 사용하는 방법

 

fkdl0048.github.io

https://unblockme.tistory.com/entry/%EC%9C%A0%EB%8B%88%ED%8B%B0C-csv-%ED%8C%8C%EC%9D%BC%EC%9D%84-%EC%9B%90%ED%95%98%EB%8A%94-%ED%83%80%EC%9E%85%EC%9C%BC%EB%A1%9C-%EC%9D%BD%EA%B8%B0Generic-%EC%82%AC%EC%9A%A9

 

[유니티/C#] csv 파일을 원하는 타입으로 읽기(Generic 사용)

string LINE_SPLIT_RE = @"\r\n|\n\r|\n|\r"; public List ReadCSV(string fileName) where T: CSVData, new() { List list = new List(); var data = Resources.Load(path + fileName) as TextAsset; string[] lines = Regex.Split(data.text, LINE_SPLIT_RE); for (int i =

unblockme.tistory.com

위 링크들은 각각 다른 방식으로 서술하고 있어서 링크를 달아봤습니다.

맨 위부터 상세 설명, 표준, 간단 구현이라고 생각됩니다.

저는 그 중 3번째인 간단 구현을 도전하여 CSV 파일을 만들어 불러오는 것을 구현해보겠습니다. 준비자료는 다음과 같습니다.

  • CSV 파일
  • 그리고 불러올 Script
  • 불러온 것을 확인할 public 변수

제가 보기 편하고 이해하기 쉽도록 처음 작성해보는 CSV는 예외처리 없이 구현한 방식을 따라서 제작해보겠습니다. 

public class CSVReader : MonoBehaviour
{
	string LINE_SPLIT_RE = @"\r\n|\n\r|\n|\r"; // 줄 내림 판정 줄  \r , \n 둘 다 개행문자.
	//string path = "NPC\\";  // 내가 사용할 리소스가 들어있는 폴더의 이름
	public List<T> ReadCSV<T>(string fileName) where T : CSVData, new() // CSVData를 계승한 클래스만 불러오기
	{
		List<T> list = new List<T>(); //여기는 맨 후반부에서 나옴.
		var data = Resources.Load(fileName) as TextAsset; // fileName 중 Text만 받아오기

		string[] lines = Regex.Split(data.text, LINE_SPLIT_RE); //개행 문자에 맞게 string 나누기

		for (int i = 2; i < lines.Length; i++) // 처음 글자들을 제거하기 위해서 2부터 시작(한글과 인덱스 이름 등)
		{
			string[] values = lines[i].Split(','); // 반점을 기준으로 index, name, description을 구분 
			for (int j = 0; j < values.Length; j++)
			{
				string value = values[j]; // 임시 대입

				value = Regex.Replace(value, "`", ","); //나눠진 csv 속 반점이나 표시 등을 제거
				values[j] = value; //대입 후 받아오기
			}

			T t = new T(); // 변환한 내용 받아줄 제네릭 생성.
			t.csvToClass(values); // 사용하고자 하는 클래스로 변환
			list.Add(t); // 리스트에 값 추가
		}

		return list;
	}
}

public class CSVData
{
	public virtual void csvToClass(string[] csvArray)
	{

	}
}

public class NPC : CSVData
{
	public string index; //
	public string name;
	public string description;

	public override void csvToClass(string[] csvArray)
	{
		index = csvArray[0];
		name = csvArray[1];
		description = csvArray[2];
	}
}

실제로 사용할 때는 각각 다른 클래스로 넣고 사용하는 것이 보기 좋겠지만, 테스트 겸 예제로써 하나의 다 적었습니다. 각 클래스는 다음과 같습니다.

  • NPC : 그냥 데이터 타입
  • CSVData : 불러올 데이터들을 하나로 취급해주는 매개체
  • CSVReader : ReadCSV를 통해 받은 string 값에 맞는 주소에 csv파일을 리스트로 변환해준다.
public class GameManager : MonoBehaviour
{
	public List<NPC> npcList = new List<NPC>();
    // Start is called before the first frame update
    void Start()
    {
		CSVReader reader = new CSVReader();
		npcList = reader.ReadCSV<NPC>("NPC"); // Resources/NPC/npc_data.csv 로드

		foreach (var npc in npcList)
		{
			Debug.Log($"NPC {npc.index}: {npc.name} - {npc.description}");
		}
	}
}

사용할 때는 다음과 같이 쓰면 됩니다. 실제로 사용할 List를 만들어 ReadCSV를 통해 return 된 값을 저장하고 활용할 수 있습니다.


CSV의 장점

유니티에서 CSV 또는 Json 등을 통해 데이터를 관리하지 않으면, ScriptableObject 또는 인스펙터 등 유니티 내부에서 수정을 거쳐줘야하는데 한 눈에 데이터를 보기가 힘들어 난해한 점이 있습니다.

그러나, CSV, Json 등의 데이터 타입은 한 공간에 모든 데이터를 가지고 있고 그것을 단순히 나눠서 쓰는 것이고 보통 한 줄에 한 데이터를 다루기 때문에 유니티에서 변수가 많아 질 경우, 세로로 변수들이 나열되는 것보다 훨씬 보기 편하여 수정하는데도 편하게 할 수 있을 것이라 생각합니다.