Unity進階技巧
前言
在遊戲製作中,我們的許多資料都是需要從檔案裡面讀取,比如常用的裝備資料,怪物資料,關卡資料等等,所以如何從檔案中讀取這些資料就變得尤為重要,因為將遊戲資料放入檔案中,會大大提高我們製作和調整遊戲的效率,所以本例中我們來看看Unity中如何通過CSV檔案來讀取遊戲資料
你將學到什麼?
- 使用Numbers製作CSV資料檔案
- Unity基礎的檔案讀取
- 通過行數和列數獲得指定的資料
一、製作CSV檔案
一般情況下,製作遊戲資料會用到表格軟體,windows下常用Excel,而Mac下常用Numbers,而這兩種軟體都可以匯出我們本例所需要的檔案——CSV檔案
首先我們開啟Numbers,新建一個檔案
新建一個Numbers檔案
然後輸入我們需要的內容,如下:
表格內容
這就簡單的製作了一個裝備資料表,每件裝備我們假設它有5個屬性:
- id:裝備ID,具有唯一性
- name:裝備的名字
- level:裝備等級
- attack:裝備增加的攻擊
- def:裝備增加的防禦
資料填寫完之後,我們就可以選擇檔案->匯出到->CSV…
匯出CSV
然後在彈出的對話方塊,直接點選下一步:
下一步
然後在接下來的對話方塊中,選擇檔名和儲存路徑:
選擇檔名和儲存路徑
匯出後,我們找到myTest.csv檔案,開啟可以看到:
**myTest.csv**檔案內容
我們可以看到我們剛剛製作的表格資料都被以文字的方式儲存下來了,並且使用了“,”號來進行分割,而CSV的中文翻譯就是逗號分隔值。但是我們會發現一個問題,為什麼後面會多了那麼多逗號呢?那是因為我們匯出的時候沒有將空的單元格刪除掉
都是空單元格的錯
所以我們匯出CSV檔案是,記得要刪除掉那些空的單元格,如下圖:
刪除空單元格後的表格
然後我們再匯出一次,並開啟匯出的檔案檢視,就會發現那些多與的逗號沒有了
終於正常的CSV檔案
二、讀取CSV檔案
有了CSV檔案後,下一步就是將它放入Unity中,並讓Unity讀取裡面的資料,首先我們新建一個Unity工程,然後將我們剛剛建立的CSV檔案放入Unity的資源目錄下,本例中我們選擇放入在*Asset->Res
CSV檔案放在Unity中的位置
然後我們新建一個名為CSV的指令碼,開啟進行編輯,輸入一下程式碼:
完整的程式碼
- 首先,如果我們要使用Unity的讀取檔案的方法,需要在開頭引入System.IO的名稱空間,這樣編輯器才會識別讀取檔案的一些方法
- 然後我們還需要使用List<T>型別的變數,所以還要引入System.Collections.Generic的名稱空間
- 然後這個CSV類是我們自己定義的一個靜態類,不需要繼承MonoBehaviour類,所以我們把繼承MonoBehaviour類的語句刪除掉
- 接著我們定義了csv和m_ArrayData兩個成員變數,第一個用來實現單例模式,第二個用來儲存從檔案讀取的內容
- 然後使用單例模式來生產這個類的例項,以後需要使用這個類的方法我們就通過GetInstance來獲取這個類的例項
- 接著我們在建構函式CSV()中,初始化m_ArrayData
- 然後我們定義了loadFile方法,有兩個引數,第一個是路徑名,第二個是檔名,通過路徑名+檔名我們就可以指定我需要讀取的檔案了
- 接著看看loadFile這個方法裡面到底做了什麼事情?首先每次讀取檔案前,我們清空一下m_ArrayData,以免資料衝突
- 然後我們定義了一個StreamReader型別的變數sr,用他來儲存檔案讀取後的最原始的資料
- 然後我們使用try{} catch{}語句,來捕獲程式異常,這個邏輯和if語句有點想,如果我們檔案讀取不成功,就會執行catch裡面的語句,在後他列印一句話來通知我檔案沒有找到,在try{}裡面使用OpenText方法來開啟我們的myTest.csv檔案
- 接著我們定義了一個line,用來臨時儲存sr裡面的每一行資料
- 然後使用一個while迴圈,把sr裡面的資料按照一行來切割,全部放入m_ArrayData中
- 最後使用close和Dispose函式將sr進行關閉和銷燬
寫完程式碼,儲存一下,然後我們在建立中新建一個空的GameObject,命名為FileController,並且為掛載一個新的指令碼檔案FileController,用來控制檔案的讀取。
FileController
然後開啟FileController指令碼,輸入下面的程式碼:
完整的程式碼
- 首先我們在Start函式中,通過CSV的例項呼叫loadFile方法來讀取我們的myTest裡面的內容,loadFile方法有兩個引數,一個是路徑名,一個是檔名稱,關於路徑名的一些注意事項,會在後面的擴充套件閱讀裡面介紹,這裡只要理解我們通過路徑名+檔名就可以指定需要讀取的檔案了
- 然後我通過for迴圈,將m_ArrayData裡所有的內容列印在程式後臺中
寫完程式碼,儲存一下,然後回到Unity編輯器,運行遊戲,可以在後臺列印中看到如下資料:
後臺列印的資料
可以看到,現在我們已經可以讀取到檔案裡面的內容了,並且是可以分解每一行的內容分別是什麼,但是這樣的解析程度還遠遠不夠,不能為我們所用,假設我們遊戲中需要生成一件裝備布衣,我們需要通過檔案獲得布衣的每一個屬性,如布衣的等級,增加的防禦值等屬性,我們就需要將每一個數據單獨提取出來,所以我們需要可以指定獲得某一個單元格里面的資料才行,下面就來看看怎麼實現
三、根據行數和列數來指定獲取資料
現在我們的m_ArrayData裡面存放的是一行的資料,也就是說其實m_ArrayData[0]就是取我們第一行的資料,m_ArrayData[1]就是取我們第二行的資料,那麼接下來我們只需要再進行一下解析,將每一行的資料按照列數來拆解,這樣我們就可以通過行數+列數來確定指定資料了,先直接上程式碼:
Paste_Image.png
- 由於這次我們需要將每一行的資料按照列數來拆解,那麼m_ArrayData裡面裝的元素就不再是string了,而是一個string數值,所以我們這邊需要修改m_ArrayData的型別為List<string[]>
- 然後我們新增一個方法getString,它有兩個引數,row是行數,col是列數,方法返回指定行數和列數的資料,資料型別是string
- 同時我們還增加一個方法getInt,它也有兩個引數,row是行數,col是列數,方法返回指定行數和列數的資料,資料型別是int,所以最後呼叫了int.Parse方法將string轉換成int型別
- 最後我們修改while迴圈中的講資料新增到m_ArrayData的語句,這裡我們呼叫Split方法,將資料以 “,” 作為分隔符,切割資料
寫完程式碼,儲存一下,然後我開啟FileController指令碼,修改程式碼如下:
完整的程式碼
- 首先讀取檔案的語句和之前一樣
- 接著我們呼叫getString方法列印行數為1,列數為1的資料
- 最後我們呼叫getInt方法列印行數為1,列數2的資料
寫完程式碼,儲存一下,大家可以先思考一下,上面列印的兩個資料分別是上面內容,然後在運行遊戲,檢查一下實際結果是否和你想象的一樣
具體對應的資料
列印結果
擴充套件閱讀
前面我們提到過,關於檔案路徑的存放位置,在本例中我們使用了Application.dataPath來指定路徑位置,關於路徑有4個型別:
- Application.dataPath:該路徑指向我們Unity編輯器的Asset資料夾
- Application.persistentDataPath:該路徑指向iOS和Android的沙盒路徑
- Application.streamingAssetsPath:streamingAsset資料夾路徑,在任何平臺都可以通過這個路徑讀取到資料夾裡的內容
- Application.temporaryCachePath:臨時資料檔案路徑
關於這4種路徑的詳細地址,大家可以試著在Unity裡面用Debug.Log語句將其打印出來,看到完整的路徑會便於理解
作者:Zui 連結:https://www.jianshu.com/p/ffda934b5e15# 來源:簡書