유니티에서 CSV를 사용하는 법..!

유니티에서 CSV는 대사를 처리하는데 많이 사용된다.

이유는 아마 기획쪽에서 엑셀로 대화 스크립트를 다루면 플밍쪽에서 쉽게 파싱하여 사용 가능하기 때문인듯 하다.

CSV..?

csv란, 필드를 쉼표로 구분한 텍스트 테이터파일이다.

  • 변환전 엑셀파일

이미지

  • 변환후 CSV파일
  • 이미지

비슷한 예로는 TSV(탭으로 구분한..)

CSVReader

이미 잘 만들어진 파싱용 스크립트를 활용하여 작업했다.

이 스크립트를 사용하기 위해선 해당 csv파일Resources폴더에 들어가야 있어야 한다.

using UnityEngine;
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;
    }
}

간단하게 살펴보면 열과 행으로 원하는 필드를 참조할 수 있는 형태의 딕셔너리를 반환해주는 함수이다.

private List<Dictionary<string, object» data_DialogCustomer = CSVReader.Read(“Dialog_Customer”);

위 처럼 사용한다.

대사를 UI에서 쉽게 접근하기 위해서 싱글톤 패턴을 사용하여 DialogueManager스크립트를 만들어서 사용했다.

using System.Collections.Generic;
using UnityEngine;

public enum CustomerState
{
    VisitGeneral, // 일반적인 방문 인사
    VisitComment, // 캐릭터 방문 인사
    RefusalComment, // 캐릭터 거절 대사
    RequestComment, // 향 요청 대사
    ResultCommentGood, // 결과 대사/
    ResultCommentNormal, // 결과 대사
    ResultCommentBad // 결과 대사
}


public class DialogueManager : Singleton<DialogueManager>
{
    protected DialogueManager() { }

    private List<Dictionary<string, object>> data_DialogCustomer = null;
    //private List<Dictionary<string, object>> data_DialogOwner = null;
    
    private enum Type 
    {
        Number,
        CustomerID,
        State,
        Content
    }
    
    void Awake()
    {
        data_DialogCustomer = CSVReader.Read("Dialog_Customer");
        //data_DialogCustomer = CSVReader.Read("Dialog_Owner");
    }
    
    /// <summary>
    /// 손님 id와 상태를 매개변수로 입력하면 해당 스크립트가 문자열로 반환됩니다.
    /// </summary>
    /// <param name="customerID">찾고자 하는 ID</param>
    /// <param name="state">현재 상태</param>
    /// <returns></returns>
    public string DialogueToString(int customerID, CustomerState state)
    {
        string temp = null;
        int id;

        id = SearchCustomerID(customerID);
        if (id == -1)
        {
            Debug.LogError("Customer id that does not exist");
        }
        
        for (int i = id; i <  data_DialogCustomer.Count; i++)
        {
            if (data_DialogCustomer[i][Type.State.ToString()].Equals((string)state.ToString()))
            {
                id = i;
                break;
            }
        }

        temp = (string)data_DialogCustomer[id][Type.Content.ToString()];

        return temp;
    }

    /// <summary>
    /// 파싱된 csv파일을 순회하며 해당 id를 찾습니다.
    /// </summary>
    /// <param name="id">검색할 손님 id</param>
    /// <returns></returns>
    private int SearchCustomerID(int id)
    {
        for (int i = 0; i <  data_DialogCustomer.Count; i++)
        {
            if ((int)data_DialogCustomer[i][Type.CustomerID.ToString()] == id)
            {
                return i;
            }
        }

        return -1;
    }
}

싱글톤 패턴은 앞서 다른 포스팅에서 다루었기 때문에 해당 글을 참고..!
싱글톤 패턴 링크

한가지 csv파일로 몽땅 넣어두게 되면 순회가 길어져 비용이 비싸지니 적당하게 분할하는것을 추천

enum으로 해당 상태를 구분하고 id로 손님을 구분하여 원하는 대사를 반환하는 함수를 만들어 두고 UI쪽에서 편하게 사용가능하도록 만들었다.


https://ko.wikipedia.org/wiki/CSV_(%ED%8C%8C%EC%9D%BC_%ED%98%95%EC%8B%9D)
https://bravenewmethod.com/2014/09/13/lightweight-csv-reader-for-unity/#comment-7111

태그: ,

카테고리:

업데이트:

댓글남기기