출처 : https://youtu.be/1EdLTF43d70?si=tQS_4TCYLQBSrOwx
CSV는 표 형태의 데이터를 쉼표(,)로 구분한 텍스트 파일이다.
이런식으로 엑셀을 이용해서 저장해도 되고, 메모장을 사용해도 된다. 이것을 저장할 때는 다른 이름으로 저장을 눌러서 확장자를 CSV로 정해주도록 하자.
Skeleton,50,10,10
Imp,100,30,50
Witch,120,20,25
Ghost,5,1,5
Demon,500,999,1000
이를 비주얼 스튜디오에서 열면 이렇게 나온다.
비주얼 스튜디오에서 열었을 때, 마지막 줄은 빈 줄이지만 추가되었을 것이다. 지워주자.
영상 설명에서는 각 요소를 다음 순서대로 작성했다.
몬스터 이름, 체력, 공력력, 경험치
Scriptable Object을 이용하여 변수를 만들어주자.
[CreateAssetMenu(fileName = "New Enemy_", menuName = "Assets/New Enemy")]
public class Enemy : ScriptableObject
{
public string enemyName;
public int hp;
public int strength;
public int xpReward;
}
유니티 어트리뷰트 중에는 다음과 같은 어트리뷰트가 있다.
[MenuItem("메뉴창에 사용할 이름")]
이를 사용하면, 에디터 위에 메뉴창에 에디터창을 만들 수 있다.
[MenuItem("Utilities/Generate Enemies")]
이를 사용하려면, UnityEditor을 선언해야 한다.
using UnityEngine;
using UnityEditor;
using System.IO;
public class CSVtoSO
{
private static string enemyCSVPath = "/CSV/Monster.csv";
[MenuItem("Utilities/Generate Enemies")]
public static void GenerateEnemies()
{
string[] allLines = File.ReadAllLines(Application.dataPath + enemyCSVPath);
foreach(string allLine in allLines)
{
string [] splitData = allLine.Split(',');
if(splitData.Length != 4)
{
Debug.Log(allLine + " Does not have 4 values");
}
Enemy enemy = ScriptableObject.CreateInstance<Enemy>();
enemy.enemyName = splitData[0];
enemy.hp = int.Parse(splitData[1]);
enemy.strength = int.Parse(splitData[2]);
enemy.xpReward = int.Parse(splitData[3]);
AssetDatabase.CreateAsset(enemy, $"Assets/CSV/{enemy.enemyName}.asset");
}
AssetDatabase.SaveAssets();
}
}
하나하나 살펴보자.
private static string enemyCSVPath = "/CSV/Monster.csv";
CSV가 저장된 파일 위치다. Project창에 Asset 이후 경로를 입력하면 된다.
이처럼, Asset 이후부터 CSV가 있는 파일 경로를 적어주자.
string[] allLines = File.ReadAllLines(Application.dataPath + enemyCSVPath);
File.IO에서 사용하는 함수다.
File.ReadAllLines(FilePath)는 경로에 있는 파일의 텍스트를 모두 읽어 한 줄 단위로 나누어 배열 형태로 내보내는 함수다.
이렇게 해도 되고 TextAsset 클래스를 이용한 뒤, String.Split('\n')으로 한 줄 씩 나눠도 된다.
foreach(string allLine in allLines)
{
string [] splitData = allLine.Split(',');
if(splitData.Length != 4)
{
Debug.Log(allLine + " Does not have 4 values");
}
Enemy enemy = ScriptableObject.CreateInstance<Enemy>();
enemy.enemyName = splitData[0];
enemy.hp = int.Parse(splitData[1]);
enemy.strength = int.Parse(splitData[2]);
enemy.xpReward = int.Parse(splitData[3]);
AssetDatabase.CreateAsset(enemy, $"Assets/CSV/{enemy.enemyName}.asset");
}
앞서 설명했듯, CSV파일은 쉼표 단위로 끊어서 저장한다. 따라서 한 줄의 데이터를 쉼표 단위로 나눈 뒤, 아까 정해둔 Scriptable Object에 저장한다.
여기서 ScriptableObject.CreateInstance<>함수는 Scriptable Object를 메모리에 생성하고 참조값을 반환하는 함수다. 그러므로 아직 파일로 생성되진 않았지만, Enemy라는 Scriptable Object의 클래스를 참조해서 쓰고 있다.
이후 AssetDatabase.CreateAsset를 이용해서 매개변수에 (생성할 파일, 파일 경로)를 정해주어 파일을 만들어주자.
AssetDatabase.SaveAssets();
마지막으로 해당함수를 이용해서 파일을 디스크에 저장하면 된다.
이런식으로 만들어진다.
지인분이 이런식으로 쓰길래 나도 한 번 만들어봤다.
using UnityEngine;
using UnityEditor;
using System.IO;
public class CSVtoSO
{
private static string enemyCSVPath = "/CSV/Monster.csv";
[MenuItem("Utilities/Generate Enemies")]
public static void GenerateEnemies()
{
string[] csvText = File.ReadAllLines(Application.dataPath + enemyCSVPath);
Enemy enemy = ScriptableObject.CreateInstance<Enemy>();
foreach(var text in csvText)
{
string[] stats = text.Split(',');
if(stats.Length != 4) Debug.LogError("This File Data Count isn't 4 count");
EnemyStat enemyStat = new EnemyStat();
enemyStat.enemyName = stats[0];
enemyStat.hp = int.Parse(stats[1]);
enemyStat.strength = int.Parse(stats[2]);
enemyStat.xpReward = int.Parse(stats[3]);
enemy.enemyStat.Add(enemyStat);
}
AssetDatabase.CreateAsset(enemy, "Assets/CSV/Enemy.asset");
AssetDatabase.SaveAssets();
}
}
잘 된다