[Unity] CSV 파일 적용하기
데이터 관리 방식에는 JSON, Scriptable Object, CSV 등이 있는데 각 사용처가 다르다. 그 중 CSV의 경우 보통 텍스트에 대한 데이터를 다룰 때에 CSV파일을 사용하게 되는데, 이를 적용하는 방법에 대해 알아보도록 하자.
CSV 파일을 적용하는 방식은 시중에 나와있는 코드가 있기 때문에 적용만 시킨다면 쉽게 사용할 수 있다.
1. 구글 스프레드 시트
구글 스프레드 시트를 이용해 액셀에서 필요한 값을 넣고, 이를 CSV파일로 변환하여 CSV파일을 만든다.
그렇다면 아래와 같은 파일명.csv라는 csv파일이 생성될 것이다.
Key,Texts
Attack1,공격력이 증가합니다 (소)
Attack2,공격력이 증가합니다 (중)
Attack3,공격력이 증가합니다 (대)
Money1,플레이어의 돈 획득량이 증가합니다 (소)
Money2,플레이어의 돈 획득량이 증가합니다 (중)
Money3,플레이어의 돈 획득량이 증가합니다 (대)
PlayerHP1,플레이어의 기본 체력이 증가합니다 (소)
PlayerHP2,플레이어의 기본 체력이 증가합니다 (중)
PlayerHP3,플레이어의 기본 체력이 증가합니다 (대)
Cost1,코스트 회복량이 증가합니다 (소)
Cost2,코스트 회복량이 증가합니다 (중)
Cost3,코스트 회복량이 증가합니다 (대)
2. Resource
Resource파일에 경로를 원하는 대로 폴더를 만들어서 관리해주면된다. 다만 폴더를 만들고 해당 경로를 잘 기억해둔 후 나중에 불러올 때 오타 등의 문제를 겪지 않도록 주의하자.
예를 들어 위와같이 되어있다면 Data/CSVFile/{파일명} 이런식으로 되어야 한다.
3. CSVReader
아래 코드는 시중에 널리 알려진 CSVReader 코드로 해당 스크립트를 통해 CSV 파일을 불러올 수 있다.
using System.Collections;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using UnityEngine;
public class CSVReader : MonoBehaviour
{
static string SPLIT_RE = @",(?=(?:[^""]*""[^""]*"")*(?![^""]*""))";
static string LINE_SPLIT_RE = @"\r\n|\n\r|\n|\r";
static char[] TRIM_CHARS = { '\"' };
public static List<Dictionary<string, object>> Read(string file)
{
var list = new List<Dictionary<string, object>>();
//TextAsset data = Resources.Load(file) as TextAsset;
// 위 주석을 해제하고 아래 두줄은 지워도 무관하다.
string path = "Data/CSVFile";
TextAsset data = GameManager.Instance.Resource.Load<TextAsset>($"{path}/{file}");
if (data == null)
{
Debug.LogError($"CSV 파일 로드 실패: {path + file}");
return list;
}
var lines = Regex.Split(data.text, LINE_SPLIT_RE);
if (lines.Length <= 1) return list;
var header = Regex.Split(lines[0], SPLIT_RE);
for (var i = 1; i < lines.Length; i++)
{
var values = Regex.Split(lines[i], SPLIT_RE);
if (values.Length == 0 || values[0] == "") continue;
var entry = new Dictionary<string, object>();
for (var j = 0; j < header.Length && j < values.Length; j++)
{
string value = values[j];
value = value.TrimStart(TRIM_CHARS).TrimEnd(TRIM_CHARS).Replace("\\", "");
object finalvalue = value;
int n;
float f;
if (int.TryParse(value, out n))
{
finalvalue = n;
}
else if (float.TryParse(value, out f))
{
finalvalue = f;
}
entry[header[j]] = finalvalue;
}
list.Add(entry);
}
return list;
}
}
주석된 코드를 다시 주석을 풀고, 아래 두 줄을 지우고 사용하도록 하자. 아래 두 줄과 error 확인을 위한 if문의 경우 입맛에 따라 약간 바꾼 부분이기 때문에 지우고 쓰도록 하자.
3. CSV 읽고 적용하기
이제 모든 준비는 끝났다. 위 코드를 보면 결국 함수를 불러오는 코드는 Read(string file) 부분이기 때문에 file이름을 통해 불러와주면 된다.
예를 들어 UpgradeText 가 파일의 이름이면
string fileName = "UpgradeText";
var data = CSVReader.Read(fileName);
이런식으로 불러와서 필요한 데이터를 사용하면 된다.
불러왔는데 그러면 어떻게 적용하냐?
저기 텍스트가 써져있는 문구를 각 버튼을 누를 때 마다 아까 csv 파일로 저장해뒀던 텍스트로 변경하려고 한다.
먼저 Key,Texts라고 액셀, csv에서 나눠뒀기 때문에 이를 Dicionary로 옮겨준다.
private Dictionary<string, string> _toggleTextsDic;
private void LoadCSVData()
{
string fileName = "UpgradeText";
var data = CSVReader.Read(fileName);
_toggleTextsDic = new Dictionary<string, string>();
foreach (var datas in data)
{
if (datas.ContainsKey("Key") && datas.ContainsKey("Texts"))
{
string key = datas["Key"].ToString();
string text = datas["Texts"].ToString();
_toggleTextsDic[key] = text;
}
}
}
key값을 가져온 key라고 하고, Texts에 있는 내용을 해당 Key의 Value로 담아주도록 하자.
이렇게 차례로 들어오게 된다.
_toggleTextsDic에 다 담았다면, 토글을 클릭했을 때 key값이 똑같다면 해당 key에 담긴 Value를 들고오게끔 하여 text에 적용하면 끝이다.
Toggles라는 enum으로 미리 바인딩해둔 토글들을 key로 지정하여 바꿔주도록 하자.
enum Toggles
{
Attack1, Attack2, Attack3,
Money1, Money2, Money3,
PlayerHP1, PlayerHP2, PlayerHP3,
Cost1, Cost2, Cost3,
}
private void OnToggleGroup(Toggles type)
{
string toggleKey = type.ToString();
// toggleTexts에 해당 키가 있으면 텍스트를 변경
if (_toggleTextsDic.ContainsKey(toggleKey))
{
GetText((int)Texts.UpgradeText).text = _toggleTextsDic[toggleKey];
}
}