1. 程式人生 > >《Unity 3D遊戲客戶端基礎框架》protobuf 導excel表格資料

《Unity 3D遊戲客戶端基礎框架》protobuf 導excel表格資料

前言:

        之前使用NPOI外掛編寫的導表工具,其實就是直接將資料進行序列化,解析時還需要進行反序列化,步驟比較繁複,最近看到Google的一個開源的專案protobuf,不僅可以用於進行excel表格資料的匯出,還能直接用於網路通訊協議的定製。

一、protobuf簡介:

        protobuf是由google公司釋出的一個開源的專案,是一款方便而又通用的資料傳輸協議。所以我們在Unity中也可以藉助protobuf來進行資料儲存網路協議兩方面的開發,這裡先說說資料儲存部分的操作,也就是:

        將.xls表格資料通過protobuf進行序列化,並在Unity中使用

1.下載資源:

2.流程圖:

   

        從上圖可看出基本的操作步驟:

  • .xls表格檔案,先通過xls_deploy_tool.py生成對應的.data檔案和.proto檔案,其中.data檔案就是表格資料序列化後的結果,而.proto檔案則是用於生成反序列化時使用的解析類的中間狀態;
  • 解析類.proto經過protoc.exe轉換成.desc檔案,用於後面通過protobuf-net等工具轉化為特定的語言,這裡我們需要得到的是C#解析類,即.cs類;
  • 在Unity中匯入protobuf-net.dll庫,在C#程式碼中呼叫上述生成的.cs解析類來解析.data中的資料。

二、導表環境配置:

1.Python相關配置:

        由於從.xls檔案生成.data和.proto,Python需要依賴Proto庫xlrd庫,安裝配置步驟:

  • setuptools:這是Python的元件安裝管理器,需要在安裝protobuff元件前進行安裝,到setuptools官網下載外掛的安裝包,解壓到指定目錄,然後使用命令列進入安裝包目錄,執行指令:python setup.py install
  • Protobuff:首先,我們將之前下載好的原始碼包protobuf-2.5.0.zip編譯包protoc-2.5.0-win32.zip壓縮包解壓到指定目錄,路徑最好不要包含中文;
  • 這裡我解壓protobuf-2.5.0.zip到的位置是“
    E:\Unity_Workplace\protobuf_250”;
  • 然後複製protoc-2.5.0-win32.zip解壓得到的protoc.exe到protobuf_250\src目錄下;
  • 在protobuf-2.5.0\python\google\protobuf下建立一個資料夾命名為compiler(安裝完成後會在此目錄下生成兩個檔案__init__.py和plugin_pb2.py);
  • 使用命令列進入到解壓後的目錄下面的Python目錄,執行:python setup.py install
  • xlrd(xls reader):這其實是讀取xls表格資料的一個工具外掛,到xlrd官網下載xrld的安裝包,解壓安裝包然後使用命令列進入安裝包目錄,執行指令:python setup.py install

2.導表外部工具:

  • xls_deploy_tool.py:這個工具其實是github上的一個開源的符合protobuff標準的根據excel自動生成匹配的PB的定義(.proto檔案)並將資料序列化後生成二進位制資料或者文字資料(.data檔案)的一個工具,github下載地址:xls_deploy_tool.py
  • protoc.exe和protogen.exe:通過上面的工具,我們得到了兩個檔案:儲存資料的.data檔案和用於解析資料的.proto檔案,但是我們在真正使用解析類來進行資料檔案的解析時,必須是高階語言,當然protobuf-net提供很多種高階語言的支援。就像我們在Unity中我們使用的是C#語言,這需要兩個工具來實現,一個是protobuf-2.5.0中的protoc.exe將.proto檔案轉換為“FileDescriptorSet”中間格式;另一個是使用protobuf-net中的protogen.exe,將中間格式的檔案轉換為最終狀態,即高階語言的解析類.cs檔案。
  • 可以到github上下載protobuf-net的原始碼:protobuf-net,下載後解壓到本地,然後進入到解壓後protobuf-net-master\protobuf-net目錄下,通過Visual Studio開啟protobuf-net.csproj:
                
  • 編譯完成後在當前目錄下面的bin\Release目錄下,生成了編譯後的檔案,其中我們需要的是protobuf-net.dll:
        
  • 將protobuf-net.dll複製到protobuf-net-master\ProtoGen目錄下,用Visual Studio開啟ProtoGen.csproj,參照上面步驟編譯ProtoGen專案,得到protobuf-net-master\ProtoGen\bin\Release目錄下面的protogen.exe及一些額外的檔案,但在真正使用時此目錄下面的所有檔案都是必須的:
        

三、樣例:

1.建立表格.xls:

        當然使用此工具進行導表的表格需要符合指定的格式,根據xls_deploy_tool.py的備註內容:

# 說明:
#   excel 的前四行用於結構定義, 其餘則為資料,按第一行區分, 分別解釋:
#       required 必有屬性
#       optional 可選屬性
#           第二行: 屬性型別
#           第三行:屬性名
#           第四行:註釋
#           資料行:屬性值
#       repeated 表明下一個屬性是repeated,即陣列
#           第二行: repeat的最大次數, excel中會重複列出該屬性
#           2011-11-29 做了修改 第二行如果是型別定義的話,則表明該列是repeated
#           但是目前只支援整形
#           第三行:無用
#           第四行:註釋
#           資料行:實際的重複次數
#       required_struct 必選結構屬性
#       optional_struct 可選結構屬性
#           第二行:結構元素個數
#           第三行:結構名
#           第四行:在上層結構中的屬性名
#           資料行:不用填

#    1  | required/optional | repeated  | required_struct/optional_struct   |
#       | ------------------| ---------:| ---------------------------------:|
#    2  | 屬性型別          |           | 結構元素個數                      |
#    3  | 屬性名            |           | 結構型別名                        |
#    4  | 註釋說明          |           | 在上層結構中的屬性名              |
#    5  | 屬性值            |           |                                   |

        當然可以參考github上下載到的樣例表格,下載tnt專案,然後複製其中python目錄下面的內容,其中xls檔案中就有一個goods_info.xls的樣例表格:

        

2.xls_deploy_tool.py轉換得到.data和.proto:

        進行導表的操作只需用在命令列中的一句指令即可完成:

python xls_deploy_tool.py sheet_name xls_path

       其中包含兩個引數:sheet_name是.xls中要進行導表的表格頁名,xls_path是要進行導表的.xls檔案的路徑。建立一個測試工程Test_protobuf,將1中的兩個檔案和protoc.exe放入其中:

        

        在命令列定位到該目錄下,然後執行指令:

call python xls_deploy_tool.py GOODS_INFO xls/goods_info.xls
        執行結束後,該目錄下多出了幾個檔案,但我們真正需要的只有兩個檔案,即.data資料檔案和.proto解析類:

        
        

3.得到最終解析類:

        protoc.exe得到中間格式檔案,假設字尾為.protodesc,使用指令:

protoc 輸入檔案路徑(.proto檔案) --descriptor_set_out=輸出檔案路徑(.protodesc)

        在步驟2中的測試工程基礎上繼續執行指令:

protoc tnt_deploy_goods_info.proto --descriptor_set_out=goods_info.protodesc
        執行此步之後,在專案中又多出了一個與.proto對應的.protodesc檔案:

        

        protogen.exe得到.cs解析類,使用指令:

protogen -i:輸入檔案路徑(.protodesc) -o:輸出檔案路徑(.cs)

        將之前生成protogen.exe時protobuf-net-master\ProtoGen\bin\Release目錄下面的所有檔案複製到當前工程中,用一個資料夾ProtoGen來存放,假如不想執行這麼繁瑣的過程,也可以直接使用我編譯好的ProtoGen檔案目錄壓縮包:ProtoGen.zip,在當前專案的根目錄下執行以下指令:

call ProtoGen\protogen -i:goods_info.protodesc -o:goods_info.cs
        執行結果,在當前目錄下生成了解析類的最終狀態goods_info.cs:

        

        當然,以上三步可以直接用批處理來完成,直接在當前專案根目錄下新建一個檔案,命名為generator.bat,內容為:

call python xls_deploy_tool.py GOODS_INFO xls/goods_info.xls
call protoc tnt_deploy_goods_info.proto --descriptor_set_out=goods_info.protodesc
call ProtoGen\protogen -i:goods_info.protodesc -o:goods_info.cs
pause
        直接雙擊此檔案即可完成以上所有操作生成最終的.data和.cs檔案

        

4.Unity匯入庫檔案:

        將幾個檔案新增到Unity工程中,將.data檔案放在Assets\StreamingAssets\DataConfig目錄下,將protobuf-net.dll和goods_info.cs放在Assets目錄下:

           

         建立一個Test.cs測試指令碼,在指令碼中using Protobuf用於匯入protobuf-net.dll中的庫,然後使用using tnt_deploy匯入導表生成的.cs表格資料解析類,指令碼具體程式碼內容為:

using UnityEngine;
using System.Collections;
using ProtoBuf;
using System.IO;
using tnt_deploy;

public class Test : MonoBehaviour {
	void Start () {
        GOODS_INFO_ARRAY goods_infos = ReadOneDataConfig<GOODS_INFO_ARRAY>("goods_info");
        Debug.Log("goods_id==================" + goods_infos.items[0].goods_id);
	}

    private T ReadOneDataConfig<T>(string FileName)
    {
        FileStream fileStream;
        fileStream = GetDataFileStream(FileName);
        if (null != fileStream)
        {
            T t = Serializer.Deserialize<T>(fileStream);
            fileStream.Close();
            return t;
        }

        return default(T);
    }
    private FileStream GetDataFileStream(string fileName)
    {
        string filePath = GetDataConfigPath(fileName);
        if (File.Exists(filePath))
        {
            FileStream fileStream = new FileStream(filePath, FileMode.Open);
            return fileStream;
        }

        return null;
    }
    private string GetDataConfigPath(string fileName)
    {
        return Application.streamingAssetsPath + "/DataConfig/" + fileName + ".data";
    }
}
        在Unity中新建一個場景,將Test.cs掛載在Main Camera主相機上,執行場景,看到列印結果,說明解析表格資料成功:

        

5.平臺相容問題:

        由於直接把protobuf-net.dll放到專案中時,在iOS中會出現JIT錯誤(ExecutionEngineException: Attempting to JIT compile method)。原因是因為iOS不允許JIT(Just In Time),只允許AOT(Ahead Of Time)。

解決方法:

        直接把protprotobuf-net-master\protobuf-net目錄下面的全部原始碼複製到Unity專案的目錄下面,但是由於protobuf-net的編譯過程是unsafe編譯,所以Unity會出現編譯報錯:

        

        需要在Assets目錄下新增一個smsc.rsp檔案,其內容很簡單,只有一行“-unsafe”,新增完成後關閉Unity然後重新開啟Unity,一切就正常了。

四、總結:

        雖然導表環境的配置過程比較繁瑣,但是配置完成之後的工作效率卻很高,而且proto具有突出的通用性,可以應用於各種語言環境。