상세 컨텐츠

본문 제목

[Unity] 유니티개발 csv 파일 읽기 관련

게임엔진관련/유니티 엔진

by AlrepondTech 2019. 3. 21. 16:15

본문

반응형

 

 

 

=======================

=======================

=======================

 

 

 

출처: https://mentum.tistory.com/214

 

 

 

참조 : https://m.blog.naver.com/PostView.nhn?blogId=bbulle&logNo=220158917236&proxyReferer=https%3A%2F%2Fwww.google.com%2F

 

[ 버전 A ]

Resource폴더에 있는 CSV 파일을 읽는 용도로 사용한다.

Resource폴더를 참조할 때 파일 확장자가 없음에 유의.

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
using UnityEngine;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text.RegularExpressions;
 
public class CSVReader
{
    static string SPLIT_RE = @",(?=(?:[^""]*""[^""]*"")*(?![^""]*""))";
    static string LINE_SPLIT_RE = @"\r\n|\n\r|\n|\r";
    static char[] TRIM_CHARS = { '\"' };
    
    public static List<Dictionary<stringobject>> Read(string file)
    {
        var list = new List<Dictionary<stringobject>>();
        TextAsset data = Resources.Load (file) as TextAsset;
        
        var lines = Regex.Split (data.text, LINE_SPLIT_RE);
        
        if(lines.Length <= 1return 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<stringobject>();
            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;
    }
}
 
cs

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
 
public class Test : MonoBehaviour
{
 
    public int _exp = 0;
 
    void Start()
    {
        List<Dictionary<stringobject>> data = CSVReader.Read("knightIdle - playerChar");
 
        for (var i = 0; i < data.Count; i++)
        {
            Debug.Log("index " + (i).ToString() + " : " + data[i]["attack"+ " " + data[i]["attackSpeed"+ " " + data[i]["criticalChance"]);
        }
 
        _exp = (int)data[0]["attack"];
        Debug.Log(_exp);
    }
}
 
cs

 

 

 

 

 

-------------------------------------------------------------------------------------------------------------

 

[ 버전 B ]

Streaming 폴더를 사용해야할 일이있어서 Streaming 폴더를 임시로 경로지정. 

여기서는 Resources.Load 대신에 StreamReader를 사용함. 파일명에서는 확장자까지.

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
using UnityEngine;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using System.IO;
 
public class CSVReader
{
    static string SPLIT_RE = @",(?=(?:[^""]*""[^""]*"")*(?![^""]*""))";
    static string LINE_SPLIT_RE = @"\r\n|\n\r|\n|\r";
    static char[] TRIM_CHARS = { '\"' };
    
    public static List<Dictionary<stringobject>> Read(string file)
    {
        var list = new List<Dictionary<stringobject>>();
        //TextAsset data = Resources.Load (file) as TextAsset;
        
        string source;
        StreamReader sr = new StreamReader(Application.dataPath + "/StreamingAssets" + "/" + file);
        source = sr.ReadToEnd();
        sr.Close();
 
        //var lines = Regex.Split(data.text, LINE_SPLIT_RE);
 
        var lines = Regex.Split(source, LINE_SPLIT_RE);
 
        if (lines.Length <= 1return 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<stringobject>();
            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;
    }
}
 
cs

 

 

-------------------------------------------------------------------------------------------------------------------------------------------

모바일과 에디터로 분리.

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
        // 에디터 혹은 PC 버전일 경우에는 : 즉 밸런싱 테스트용 빌드일 경우에는! 스트리밍 에셋에서 불러옵니다.
#if (UNITY_EDITOR || UNITY_STANDALONE)
 
        // 경로에 파일 존재하는지 확인
        string dir = Application.dataPath + "/StreamingAssets/" + file + ".csv";
        if (!File.Exists(dir))
        {
            Debug.Log(file + "파일이 존재하지않습니다.");
            return list;
        }
        
        string source;
        StreamReader sr = new StreamReader(Application.dataPath + "/StreamingAssets/" + file + ".csv");
        source = sr.ReadToEnd();
        sr.Close();
        var lines = Regex.Split(source, LINE_SPLIT_RE);
#else
 
        TextAsset data = Resources.Load (file) as TextAsset;
        var lines = Regex.Split(data.text, LINE_SPLIT_RE);
#endif
cs

 

 

[ 공통 : 오브젝트 형식 데이터 파싱 ]

 오브젝트형식으로 리턴되는 파싱은 int.Parse(data.ToString())

 

1
2
3
4
5
6
7
8
9
10
11
    // 오브젝트 -> float로 파싱
    public float FloatParse(object obj)
    {
        return float.Parse(obj.ToString());
    }
 
    // 오브젝트 -> int로 파싱
    public int IntParse(object obj)
    {
        return int.Parse(obj.ToString());
    }
cs

 

 

[ 공통 : csv 편집기 ]

 엑셀보다는 Rons CSV Editor를 추천함. 엑셀은 무겁기도하고, 열고있으면 Violation Error 나기도하고.

 https://www.ronsplace.eu/Products/RonsEditor/Download

 

 

 

=======================

=======================

=======================

 

 

 

 

 

출처: http://blog.naver.com/PostView.nhn?blogId=ateliersera&logNo=220730240253&categoryNo=44&parentCategoryNo=15&viewDate=&currentPage=5&postListTopCurrentPage=1&from=postList

 

 

대만,일본,중국  심지어 포루투갈이라거나 이태리,프랑스어 등을 동시에 10개국씩 작업하다보면 깨지는 경우가 많습니다.

 

답은 간단한데, 엑셀에서 CSV파일을 만드는 것이 아니라, 다음과 같은 방법으로 제작하면 됩니다.

 

1. 엑셀에서 다른이름으로 저장 -> .txt 파일로 저장 합니다.

2. 위에서 만든 텍스트 문서를 노트패드로 열은 후 UTF-8로 저장 합니다.

3. UTF-8로 저장한 문서를 노트패드++ 등으로 불러옵니다.

 

전체 선택을 하고, ctrl + h 를 누른후 정규식을 선택 해서 바꿔야 합니다. 

찾을 말은 \t  

바꿀 말은 , 

입니다.  \t 이 곧 탭 입니다. 텍스트 저장은 탭으로 분류됩니다. 

 

이렇게 바꾼것을 저장하면 됩니다.  그리고, .txt 를 csv로 필요하면 확장자 명을 바꾸면 됩니다. 

 

 

---------------------------------------------------------------

엑셀 데이터 자체를 UTF-8로 저장하기 * 안 먹히는 경우가 많습니다.

1. 다른이름으로 저장 을 눌러서 다이얼로그 창을 띄운다.

2. 하단에 있는 도구 - 웹 옵션을 클릭 한다

3. 웹 옵션 - 인코딩에 들어가서, 문서를 다음 형식으로 저장 -> 한국어로 되어 있는데, 유니코드(UTF-8)로 변경한다

 

애초에 UTF-8로 저장되면 안깨지는데, 이게 될때가 있고 안될때가 있습니다.. 안된다 싶으면 위에 방법을, 된다면 아래에 방법을 사용하시면 됩니다. 

 

 

 

 

 

 

 

 

=======================

=======================

=======================

 

 

 

 

반응형

 

 

728x90

 

 

 

출처: https://m.blog.naver.com/PostView.nhn?blogId=bbulle&logNo=220158917236&proxyReferer=https%3A%2F%2Fwww.google.com%2F

 

 

 

 제가 전에 다니던 게임회사 에서는 보통

 

게임 데이터 관리를 csv 로 했었습니다. 

(json 도 쓰긴 했었는데 결국 csv 로 대동단결 되었음)

 

 

 

그때는 제 직책이 게임 기획자 였는데

 

제가 엑셀로 데이터 테이블을 만들고

 

이를 csv 파일로 익스포트해서 프로그래머에게 던져주면

 

프로그래머가 알아서 csv 파일을 읽는 코드를 만들고 데이터를 적용 시켰었죠

 

 

그런데 이제는 제가 혼자 작업하고 있기 때문에

 

CSV 파일을 읽는 부분을 직접 만들어야 겠네요ㅎㅎ

 

 

 

그럼 이제 부터 엑셀 파일을 csv 파일로 내보내고

 

이를 유니티로 읽어들이는 과정에 대해서 알아보겠습니다.

 

 

 

액셀 데이터를 csv 파일로 내보내기

 

 

 

대충 이러한 데이터 테이블을 작성해 보았습니다.

 

여기서 중요한 점은 가장 위의 한줄은 header 라고 

 

엑셀의 가장 윗줄 처럼 하위 항목들이 무엇인지를 알려주는 부분입니다.

 

 

 

저장/보내기 - 파일 형식 변경 - 다른 이름으로 저장 

 

 

파일 형식을 CSV 로 선택을 하고 저장을 해 줍니다.

 

 

이렇게 생성된 파일을

 

메모장으로 열어보거나 위와 같이 편집을 눌러보면

 

 

 

이렇게 값이 들어가 있음을 확인할 수 있습니다.

 

가장 윗줄은 헤더이고 콤마(,)를 통해 각 값들을 구분해 주는 형식입니다.

 

 

 

 

유니티로 CSV 파일을 읽어보자

 

 

Assets 폴더 아래에 Resources 라는 폴더를 만들어 주고

 

위에서 만들었던 CSV 파일을 넣어 줍니다.

 

 

 

그리고 이 CSVReader.cs 스크립트를

 

프로젝트에 임포트 시켜줍니다. (첨부되어 있음)

 

앞으로 csv 파일을 읽어 들일때 위의 CSVReader 클래스를 사용하게 됩니다.

 

 

 

참고로 스크립트는 제가 작성한것이 아니고

 

구글링을 하면서 발견한 공개 CSVReader 스크립트 중에서

 

가장 마음에 드는 녀석을 줏어온 것입니다.

 

(출처는 요기 : http://bravenewmethod.com/2014/09/13/lightweight-csv-reader-for-unity/#comment-7111)

 

 

 

 

 

=======================

=======================

=======================

 

 

 

 

출처: https://bravenewmethod.com/2014/09/13/lightweight-csv-reader-for-unity/#comment-7111

 

Managing game data in Unity scene objects can get really painful especially when more than one people needs to edit the same thing. It’s usually better to have some data in CSV file where it can be controlled centrally.

When facing this problem I couldn’t find CSV reader for Unity that would have been exactly what I need. i.e. not be very buggy, huge or require new assembly dependencies.
So here is very simple CSV reader for Unity. It is bare bones but still robust enough parse quoted text and comma’s inside text. Reader assumes that csv files are in Resources folder of your Unity project.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
using UnityEngine;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text.RegularExpressions;
 
public class CSVReader
{
    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;
 
        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;
    }
}

Drop this in your Scripts folder as CSVReader.cs and make folder Resources under your Assets folder. Put there any CSV files you want to use.

Example CSV file example.csv in Resources folder.

1
2
3
4
name,age,speed,description
cat,2,4.5,"cat stalks, jumps and meows"
dog,2,5.5,dog barks
fish,1,1.1,fish swims

How to use

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
 
public class Main : MonoBehaviour {
 
    void Awake() {
 
        List<Dictionary<string,object>> data = CSVReader.Read ("example");
 
        for(var i=0; i < data.Count; i++) {
            print ("name " + data[i]["name"] + " " +
                   "age " + data[i]["age"] + " " +
                   "speed " + data[i]["speed"] + " " +
                   "desc " + data[i]["description"]);
        }
 
    }
 
    // Use this for initialization
    void Start () {
    }
 
    // Update is called once per frame
    void Update () {
 
    }
}

See full example code in Github: https://github.com/tikonen/blog/tree/master/csvreader

 

 

 

=======================

=======================

=======================

 

 

 

 

반응형


관련글 더보기

댓글 영역