일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- 오브젝트이동
- 라즈베리파이
- 미니적도의
- 번역
- coroutine
- This is EVE
- 유루캠
- 리눅스
- 킥스타터
- 게임제작
- 이브뉴스24
- 미타니
- DX라이브러리
- 포크스푼
- 천체사진
- 자율비행
- 언성스토리
- 오픈스택
- 스카이트래커
- C언어
- centos
- 드론
- 데포르메
- 온라인
- 유니티
- 점상
- 이브
- UI
- inputsystem
- 이브온라인
- Today
- Total
게임개발 예제모음
CSV파일을 로드하여 TEXT 출력 본문
○ 구현목표
- 게임을 진행하는 도중 등장인물들간의 대화를 작성하게 되는경우는 거의 필수적으로 발생 - 각각의 대화를 NPC오브젝트에 직접 하드코딩을 하는 방법도 있으니 유지보수가 어렵고 코드가 지저분해진다 - 별도의 CSV파일을 작성하여 내용을 읽어들여 TEXT를 뿌려주는 기능을 구현한다 - Resources폴더를 사용하지 않는다 요구조건 - TextMeshPro에서 사용할 폰트는 이미 설치되어있다고 가정한다 |
○ 참고자료
https://gist.github.com/SiarheiPilat/de4688651f106e7993a7e2fdb743cac4
A lightweight CSV reader for Unity.
A lightweight CSV reader for Unity. GitHub Gist: instantly share code, notes, and snippets.
gist.github.com
※ 국내에서 찾아볼 수 있는 대부분의 자료는 위 링크를 참고하여 작성된 자료들이라고 생각됨
※ 이 포스트에서도 동일하게 위 자료를 참고하여 약간의 커스터마이징을 진행함
○ 대화에 사용될 CSV파일 준비 (Sample.csv)
※ 한글을 출력하고 싶다면 반드시 UTF-8 형식으로 작성되어야 함
○ 대화용 UI구성
※ 배경(Box)은 [ UI → panel ], 텍스트는 [ UI → Text - TextMeshPro]
○ CSV파일 임포트
※ 상기 참고자료의 코드를 그대로 사용하게 되면 반드시 Resources폴더를 사용해야 함
※ 구현 목표에 따라 별도의 폴더에 임포트 한다
○ CSV파일 로더 작성
① 로더 전용 오브젝트 작성 [ Create Empty ]를 통하여 비어있는 오브젝트 작성
② 프로젝트 윈도우에서 [ Create → MonoBehaviour Script ]를 통해 LoadCsv스크립트 작성 및 어태치
③ 스크립트 작성
using System.Collections.Generic;
using UnityEngine;
using System.Text.RegularExpressions;
public class LoadCsv : 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(TextAsset file)
//메소드에서 매개변수로 CSV를 직접 받아 오도록 작성
{
var list = new List<Dictionary<string, object>>();
//CSV파일을 직접 매개변수로 사용하기 때문에 Resources.Load는 필요 하지 않음
//Resources폴더를 사용하지 않음
var lines = Regex.Split(file.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;
}
}
※ NPC오브젝트 등 해당 스크립트를 언제든지 불러와서 사용할 수 있도록 public static으로 작성
※ 위 메소드를 호출하는 기본 형
//메소드 호출
List<Dictionary<string, object>> data = LoadCsv.Read(filename);
//값 출력
Debug.Log(data.[int 행번호]["칼럼명"])
//앞 [] : int타입 행번호, 뒤 [] : string타입 칼럼명을 쌍따옴표("") 안에 직접 입력
○ NPC역할을 하게 될 오브젝트 생성 및 스크립트 작성
① Empty오브젝트에 스크립트(TextManager)만 추가하여 간단하게 진행
② 스크립 작성 - (1)
using TMPro;
using UnityEngine;
public class TextManager : MonoBehaviour
{
[SerializeField] TextAsset csvFile; //불러오게 될 CSV파일용 변수
[SerializeField] TextMeshProUGUI nameTextBox; //nameBox의 text 변수
[SerializeField] TextMeshProUGUI messageTextBox; //messageBox의 text 변수
}
③ 스크립트 작성 - (2) : 선언한 변수에 오브젝트 및 어셋 어태치
④ 스크립트 작성 - (3) : CSV파일을 읽어들이기 위한 구조체 작성 및 구조체 배열 선언
TextSturct[] myText; //② 구조체 배열 선언
//① 구조체 선언
struct TextSturct
{
public string nameText;
public string messageText;
}
※ 보통 CSV파일의 내용이 단 한줄만 존재하는 것은 아니기 때문에 구조체 배열을 선언 하여 진행
※ 이 포스팅의 내용처럼 단 한줄만 출력한다면 구조체 및 배열없이 직접 텍스트를 출력해도 무방함
⑤ 스크립트 작성 - (4) : LoadCSV 호출 메소드 작성
using System.Collections.Generic;
public class TextManager : MonoBehaviour
{
void GetText(TextAsset filename)
{
List<Dictionary<string, object>> data = LoadCsv.Read(filename);
//LoadCsv의 메소드를 호출하여 CSV파일을 list에 로딩
myText = new TextSturct[data.Count];
//CSV파일을 배열에 저장
for (int i = 0; i < data.Count; i++) //각각의 값을 구조체 배열에 저장
{
string tempName = data[i]["NAME"].ToString();
string tempText = data[i]["TEXT"].ToString();
myText[i].nameText = tempName;
myText[i].messageText = tempText;
}
}
}
⑥ 스크립트 작성 - (5) : Update 작성
void Update()
{
GetText(csvFile); //csvFile에 어태치한 CSV파일을 매개변수로 하여 메소드 호출
nameTextBox.text = myText[0].nameText; //nameText 출력
messageTextBox.text = myText[0].messageText; //messageText 출력
}
※ myText[0]만 출력한 이유는 샘플 CSV가 한줄짜리 데이터이기 때문임
※ 필요에 따라 for 또는 if 등등을 활용하여 커스텀 하여 사용
○ 실행 테스트
○ 스크립트 전문
① LoadCsv.cs
using System.Collections.Generic;
using UnityEngine;
using System.Text.RegularExpressions;
public class LoadCsv : 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(TextAsset file)
{
var list = new List<Dictionary<string, object>>();
var lines = Regex.Split(file.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;
}
}
② TextManager.cs
using System.Collections.Generic;
using TMPro;
using UnityEngine;
public class TextManager : MonoBehaviour
{
[SerializeField] TextAsset csvFile;
[SerializeField] TextMeshProUGUI messageTextBox;
[SerializeField] TextMeshProUGUI nameTextBox;
TextSturct[] myText;
void Update()
{
GetText(csvFile);
nameTextBox.text = myText[0].nameText;
messageTextBox.text = myText[0].messageText;
}
void GetText(TextAsset filename)
{
List<Dictionary<string, object>> data = LoadCsv.Read(filename);
myText = new TextSturct[data.Count];
for (int i = 0; i < data.Count; i++)
{
string tempName = data[i]["NAME"].ToString();
string tempText = data[i]["TEXT"].ToString();
myText[i].nameText = tempName;
myText[i].messageText = tempText;
}
}
struct TextSturct
{
public string nameText;
public string messageText;
}
}
'유니티 메모장' 카테고리의 다른 글
함수에서 특정 자료 반환하기 (0) | 2025.06.10 |
---|---|
스크롤뷰 방향키로 조작하기 (0) | 2025.06.09 |
현재 선택중인 버튼 확인 (0) | 2025.06.05 |
UI만들기 : 하위 메뉴버튼 이동 및 복귀 (0) | 2025.06.04 |
UI 만들기 : 버튼 선택 (0) | 2025.06.03 |