Unity如何讀取外部純文字文件?

在作對話系統編譯器(可以在Unity內執行的吉里吉里)時,整理出的Unity讀取外部變數的方法

前言

隨著寫過的專案越來越多,各種稀奇古怪的需求就會冒出來。最近寫的一支角色對話編譯器就是個不錯的例子。

該編譯器的流程如下:

dbc7a3581c6165dfcf52eed8ff02fb9c0
在測試時當然是直接把腳本字串打在code的string內直接丟進編譯器內,而之後寫的專案則是已經有人弄了個腳本管理系統,能直接抓到腳本的字串。
而新的專案沒有這些方便的工具所以就自己處理吧!

試錯

一開始就是用最傳統的System.IO大法,先使用Application.dataPath抓到專案的路徑,然後直接上網Copy讀取檔案的程式碼

using (StreamReader sr = new StreamReader(path+fileName))
{
    String line = sr.ReadToEnd();
    Console.WriteLine(line);
}

唷西,按下play,居然出人意料的一點問題都沒有。於是該寫的寫該call的call,把東西弄完做輸出測試時,萬惡的NullReferenceException出現了!!
什麼?東西讀不出來?明明在編輯器裡面一點問題都沒有啊?

沒關係,等我谷哥出來你就死定了。

解答

在谷哥的幫忙下,得知了路徑本身是沒有問題的Application.dataPath會指向專案路徑,或是Build後的安裝路徑,但問題出在Unity將專案Build出來後會將Assets內的東西序列化、壓縮、打包,所以在遊戲的安裝路徑內是找不到檔案的,除非你打算在專案輸出後再用其它方式把檔案放進去(不過如果你是Android、iOS專案可能就無解了)。

同時谷哥也提到了Unity提供的另外兩種方式︰

  • Resources.Load
  • Application.streamingAssetsPath

Resources.Load

查到Resources.Load的時候其實有點疑惑,Resources.Load不是只能讀Unity提供的檔案格式嗎?文字檔要轉型成什麼?Resources.Load<string>(path)?

官網查後得知Unity提供了TextAsset格式用以Load文字文件,但目前僅支援下列副檔名

 .txt
 .html
 .htm
 .xml
 .bytes
 .json
 .csv
 .yaml
 .fnt

真相大白後就能簡單的把東西讀出來了

  var str = Resources.Load<TextAsset>(fileName).ToString();
  
  //或是干脆連轉型都懶了
  var str = Resources.Load(fileName).ToString();

Build出來測試也沒問題。

Application.streamingAssetsPath

另一個查到的方法是用Application.streamingAssetsPath,與Resources.Load很類似,要將檔案放到StreamAssets的系統保留資料夾內,但讀取時需要用WWW來讀取,在網上查到的讀取代碼如下

IEnumerator LoadXML()
{
    string sPath= Application.streamingAssetsPath + "/Test.xml";
    WWW www = new WWW(sPath);
    yield return www;
    _result = www.text;
}

讀取時還要開StartCoroutine異步讀取,以目前的需求來說不太方便,因此先擱置吧,有機會再提。

參考

RUNTIME-Unity3D移动平台动态读取外部文件全解析
Unity-Manual