'IT 관련/유니티 엔진'에 해당되는 글 4건

 유니티 엔진으로 모바일 게임을 개발하던 중, 한글 파일을 읽으면 한글이 깨지는 문제를 겪였다.

 문제 원인은 모바일 기기의 기본 인코딩 방식이 euc-kr가 아니었고, euc-kr 인코딩을 지원하지도 않는 것이었다.


1. 한글 인코딩으로 변환

 읽어온 데이터를 한글 인코딩으로 변환하면 문제는 해결된다.

 이는 다음 코드를 이용하여 구현할 수 있다.


System.Text.Encoding.GetEncoding("euc-kr"); : euc-kr 인코딩 클래스 변수를 얻어옴


예제 

//결과 텍스트(인코딩 전) byte[] resultBytes = www.bytes; System.Text.Encoding euc = System.Text.Encoding.GetEncoding("euc-kr"); //한글을 읽기 위한 euc-kr 인코딩 //읽은 파일 데이터를 euc-kr 인코딩으로 변환 string convertedString = euc.GetString(resultBytes);


 그런데 System.Text.Encoding.GetEncoding("euc-kr") 부분에서 에러가 발생했다.


 유니티 에디터에서는 아무런 문제도, 경고도 뜨지 않았는데, 안드로이드 기기에서 테스팅 할 때만 이 코드에서 오류가 발생해서 문제를 또 찾아봤는데, 인코딩과 관련된 dll 파일이 없는게 원인이었다.


 문제 해결을 위해서는 인코딩과 관련된 dll인 I18N.dll, I18N.CJK.dll 파일을 복사해서 유니티 프로젝트의 Assets/Plugins 디렉토리에 넣고 새로 빌드하면 된다.


 이 두 dll 파일들은 ...\Unity\Editor\Data\Mono\lib\mono\unity 디렉토리 내에 있으니 복사해서 사용하면 된다.


dll 파일들 위치


 

2. 레퍼런스

https://202psj.tistory.com/1297 - 유니티 모바일에서 한글 인코딩 사용하기


https://forum.unity.com/threads/solved-application-crash-with-notsupportedexception.415325/ - GetEncoding() 에러 해결 방법



블로그 이미지

서기리보이

,

 WWW 클래스를 이용하면 모바일에서도 StreaminAssets을 읽을 수 있지만, 이 방법 보다는 BetterStreamingAssets 오픈소스 라이브러리를 활용하는 것을 추천한다.

 BetterStreamingAssets가 이용하기가 더 편하고, 디렉토리 확인/검색/byte로 읽기/string으로 읽기, 이런 기능들을 제공하기 때문에 구현하기가 더 편하다.

(https://invincibletyphoon.tistory.com/47)


WWW를 이용한 리퀘스트로 Streaming Asset 읽기

 StreamingAsset이 파일을 복사해서 타겟 컴퓨터에 집어 넣어준다는 사실은 알았지만, C#의 기본 파일처리 클래스로는 작업할 수 없다. 안드로이드에서 StreamingAssets을 읽기 위해서는 WWW 클래스를 이용해서 비동기 방식으로 파일을 읽어 올 수 있다.


 이를 위해서 Streaming Assets 내의 파일 경로는 다음과 같이 구한다.

string streamingAssetsDirectory = "jar:file://" + Application.dataPath + "!/assets/";


//찾으려는 파일 경로 filePath = streamingAssetsDirectory + filename;


 이 파일 경로의 데이터를 WWW클래스를 이용하여 얻어온다.

//안드로이드 내의 파일들은 .jar 형식으로 압축되어 있어서 StreamReader 등의 일반적인 파일 처리 방식을 사용할 수 없다. //대신에 www 리퀘스트를 보내서 파일 데이터를 얻어온다. WWW www = new WWW(filePath); while (!www.isDone) { } //완료될 때까지 대기(원래 www는 비동기 처리방식임) //결과 텍스트(인코딩 전) byte[] resultBytes = www.bytes;



파일이 한글을 포함하고 있는 경우 인코딩을 euc-kr로 변환하는 과정을 거쳐야한다.

System.Text.Encoding euc = System.Text.Encoding.GetEncoding("euc-kr"); //한글을 읽기 위한 euc-kr 인코딩 //읽은 파일 데이터를 euc-kr 인코딩으로 변환 string convertedString = euc.GetString(resultBytes); readResult.text = convertedString; readResult.text += "\ndone";

readResult.text가 최종적으로 읽은 결과이고, 이는 UI에 출력되도록 구현했다.



 전체 코드

using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; using UnityEngine.Android; using UnityEngine.Networking; public class TestReader : MonoBehaviour { public void read(string filename) { string filePath = ""; GameObject readResultObj = GameObject.Find("ReadResult"); Text readResult = readResultObj.GetComponent<Text>(); readResult.text = ""; //PC 유니티 에디터 if (Application.platform == RuntimePlatform.WindowsEditor) { filePath = Application.dataPath + filename; System.IO.StreamReader sr = new System.IO.StreamReader(filePath, System.Text.Encoding.GetEncoding("euc-kr")); string[] line = System.Text.RegularExpressions.Regex.Split(sr.ReadToEnd(), "\r\n"); foreach (string str in line) { readResult.text += str; readResult.text += "\n"; } } else if (Application.platform == RuntimePlatform.Android) //안드로이드 { //유니티 프로젝트 에디터의 Assets/StreamingAssets 내의 파일들은 이 경로내에 복사된다. string streamingAssetsDirectory = "jar:file://" + Application.dataPath + "!/assets/"; //찾으려는 파일 경로 filePath = streamingAssetsDirectory + filename; //안드로이드 내의 파일들은 .jar 형식으로 압축되어 있어서 StreamReader 등의 일반적인 파일 처리 방식을 사용할 수 없다. //대신에 www 리퀘스트를 보내서 파일 데이터를 얻어온다. WWW www = new WWW(filePath); while (!www.isDone) { } //완료될 때까지 대기(원래 www는 비동기 처리방식임) //결과 텍스트(인코딩 전) byte[] resultBytes = www.bytes; System.Text.Encoding euc = System.Text.Encoding.GetEncoding("euc-kr"); //한글을 읽기 위한 euc-kr 인코딩 System.Text.Encoding defaultEncoding = System.Text.Encoding.Default; //시스템의 기본 인코딩 //byte[] resultBytes = euc.GetBytes(result); //읽은 파일 데이터를 euc-kr 인코딩으로 변환 //byte[] convertedBytes = System.Text.Encoding.Convert(euc, System.Text.Encoding.UTF8, resultBytes); string convertedString = euc.GetString(resultBytes); readResult.text = convertedString; readResult.text += "\ndone"; } } }


 한글 인코딩 관련으로 또 문제가 있는데, 이 부분도 포스팅으로 다루었으니 링크로 첨부한다.

https://invincibletyphoon.tistory.com/49?category=816145

'IT 관련 > 유니티 엔진' 카테고리의 다른 글

유니티 모바일 한글 깨짐  (2) 2019.09.25
Better Streaming Asset  (5) 2019.09.25
유니티 스트리밍 에셋(Unity Streaming Assets)  (0) 2019.09.24
블로그 이미지

서기리보이

,

모바일에서 Streaming Asset을 사용하려니 WWW 클래스를 이용한 비동기 처리 방식이라서 코드가 보기 안좋게 짜여지는 것도 있었고, 디렉토리 존재 여부 확인, 검색 기능 등이 없으니 불편했었다.


 더 나은 방법이 없을까 하다가, BetterStreamingAssets이라는 오픈소스에 대해서 알게되었다.(https://assetstore.unity.com/packages/tools/input-management/better-streaming-assets-103788)


1. BetterStreamingAssets란

 BetterStreamingAsset은 StreamingAsset 파일 처리를 더 쉽게 해주는 오픈소스로, MIT 라이센스로 제공되기 때문에 개발한 소프트웨어 내에 사용했다고 기록만 남겨주면 상용으로도 이용 가능하다.

 유니티 에디터의 에셋 스토어에서 Better Streaming Asset을 검색해서 Import하고, 폴더 내에서 README 파일을 보고 따라하면 되기때문에 이용하기는 쉽다.


2. 라이브러리 사용 방법

관련 함수들

static void BetterStreaminAssets.Initialize();

BetterStreamingAssets 라이브러리를 초기화한다.

메인 스레드 내에서 호출해야한다.


static bool DirectoryExists(string path);

path 디렉토리가 존재하는지 여부를 확인한다.


static string[] GetFiles(string path, string searchPattern, SearchOption searchOption);

path에서 searchPattern으로 이름을 가진 파일들을 얻어온다.

searchPattern은 파일 명을 이용할 수 있고, *.png 같은 형식도 이용할 수 있다.

searchOption은SearchOption.AllDirectories, SearchOption.TopDirectoryOnly 두가지를 이용 할 수 있다.

SearchOption.AllDirectoriess 옵션은 하위 디렉토리까지 모두 검색하고,

SearchOption.TopDirectoryOnly은 해당 디렉토리만 검색한다.


static string ReadAllText(string path);

파일 내용을 string 형식으로 모두 읽어온다.


static byte[] ReadAllBytes(string path);

파일 내용을 byte[] 형식으로 모두 읽어온다.

 모두 static 형식이기 때문에 BetterStreamingAssets.ReadAllText(...) 형식으로 호출하면 된다.


 BetterStreamingAsset을 이용하려면, 최초로 한번 초기화해주어야한다.

BetterStreaminAssets.Initialize();


 파일 리스트는 다음과 같이 얻어올 수 있다.

//모든 .xml 파일 리스트를 얻어옴

string[] paths = BetterStreamingAssets.GetFiles("\", "*.xml", SearchOption.AllDirectories);


 파일은 다음과 같이 읽을 수 있다. 이는 한글을 읽기 위해서 한글 인코딩으로 변환하는 과정을 포함한 것이다.

public string readFIle(string filename) { byte[] byteContents = BetterStreamingAssets.ReadAllBytes(filename); string contentsString = System.Text.Encoding.GetEncoding("euc-kr").GetString(byteContents);

return contentsString; }


호출 예제

readFile("WeaponDataSet/Weapon_001.csv");


 개인적으로 BetterStreamingAssets를 이용하는 방법이 WWW 클래스를 쓰는 것 보다 훨씬 편했다. 이래서 다들 오픈소스 쓰라고 하는가보다 싶었다.


 한글 인코딩 관련으로 또 문제가 있는데, 이 부분도 포스팅으로 다루었으니 링크로 첨부한다.

https://invincibletyphoon.tistory.com/49?category=816145

블로그 이미지

서기리보이

,

유니티 엔진으로 모바일 게임을 개발하던 중, 유니티  에디터에서는 분명히 잘 되던 파일 입출력이 안드로이드로 빌드해서 테스트하면 안되는 문제를 겪었다. 

 이 문제에 대해서 알아보니, 유니티 에디터에서는 에셋 폴더에 접근 가능하지만, 빌드 버전에서는 접근이 불가능하다는 것을 알게 되었다.(https://answers.unity.com/questions/272486/cannot-read-or-write-a-txt-file-after-build.html)

 빌드버전에서 에셋 파일을 사용하기 위해서는 Streaming Asset을 사용할 수 있다.


1. Streaming Asset이란

 에셋 폴더 내의 폴더들 중 특별취급되는 폴더 중 하나다.(http://wiki.unity3d.com/index.php/Special_Folder_Names_in_your_Assets_Folder)

 이 폴더에 포함된 파일들은 빌드 타겟 컴퓨터(안드로이드든, ios든 윈도우든)로 복사되어 들어가고, 읽기 전용이라서 게임 도중에 데이터 저장은 불가능하다.

 이 방법을 사용하려면 유니티 엔진에서 에셋 폴더 내에 StreamingAssets 라는 폴더를 만들고 ,그 안에 파일을 넣으면 이용 가능하다.

StraminAssets 폴더를 Asset 폴더 내에 배치하여 사용한다.


2. Streaming Assets 이용 방법

  Streaming Assets를 이용하는 방법은 2가지가 있다. WWW 클래스를 이용하는 방법, BetterStreamingAssets 오픈소스 라이브러리를 이용하는 방법, 이렇게 2가지인데, 각 방법은 각각의 포스팅으로 다루었으니 링크를 참조하기 바란다.

https://invincibletyphoon.tistory.com/48 (WWW Class) (비추천)

https://invincibletyphoon.tistory.com/47 (BetterStreaminAssets) (추천)



3. 레퍼런스

https://answers.unity.com/questions/272486/cannot-read-or-write-a-txt-file-after-build.html - 에디터에서는 에셋 폴더 접근이 가능하지만, 빌드버전에서는 불가능하다.

http://wiki.unity3d.com/index.php/Special_Folder_Names_in_your_Assets_Folder - 유니티 에셋 내의 특별한 디렉토리명들

https://docs.unity3d.com/2018.4/Documentation/Manual/StreamingAssets.html - 유니티 StreamingAssets 레퍼런스

https://stackoverflow.com/questions/20188742/writing-to-unitys-streamingassets-folder-at-runtime-on-android - StreamingAsset은 읽기 전용임.

http://memocube.blogspot.com/2014/04/blog-post.html - 유니티 DataPath 정리

https://ajh322.tistory.com/135 - 유니티 안드로이드 파일입출력 예제




'IT 관련 > 유니티 엔진' 카테고리의 다른 글

유니티 모바일 한글 깨짐  (2) 2019.09.25
WWW 클래스를 이용한 StreamingAsset 처리  (0) 2019.09.25
Better Streaming Asset  (5) 2019.09.25
블로그 이미지

서기리보이

,