Unity3D客户端和Java服务端使用Protobuf
轉(zhuǎn)自:http://blog.csdn.net/kakashi8841/article/details/17334493
前幾天有位網(wǎng)友問(wèn)我關(guān)于Unity3D里面使用Protobuf的方法,一時(shí)有事拖到現(xiàn)在才寫(xiě)這篇文章,不好意思哈。
本文測(cè)試環(huán)境:
系統(tǒng):WINDOWS 7(第3、6步)、OS X 10.9(第4步)
軟件:VS 2012(第3、6步)、Eclipse(第5、6步)
硬件:iPad 2(第4步)、Macbook Pro Mid 2012(第4步)
?
文章目錄:
1、關(guān)于Protobuf的C#實(shí)現(xiàn)
2、為什么有些Protobuf發(fā)布到iOS就用不了,甚至有些在PC都用不了?
3、手動(dòng)處理C#版本的Protobuf
?
? ? 3.1、創(chuàng)建一個(gè)C#工程,先手動(dòng)創(chuàng)建每一個(gè)要通過(guò)Protobuf序列化或反序列化的數(shù)據(jù)模型類(lèi),然后導(dǎo)出dll
? ? 3.2、創(chuàng)建一個(gè)用于序列化的C#工程,然后運(yùn)行生成dll
? ? 3.3、將上面兩個(gè)工程生成的dll拖到unity中
4、在Unity中反序列化Protobuf
5、服務(wù)端Java也用Protobuf
6、太煩了?!客戶端也要自動(dòng)處理Protobuf
?
1、關(guān)于Protobuf的C#實(shí)現(xiàn)
首先,U3D里面Protobuf使用的是C#的實(shí)現(xiàn),那么目前有幾個(gè)可選的C#實(shí)現(xiàn):
C#: http://code.google.com/p/protobuf-csharp-port
C#: http://code.google.com/p/protosharp/
C#: https://silentorbit.com/protobuf/
C#/.NET/WCF/VB: http://code.google.com/p/protobuf-net/
?
我這里選用的是http://code.google.com/p/protobuf-net/(你可以在https://code.google.com/p/protobuf-net/downloads/list?這里下載到他的代碼和工具),它比較好的一點(diǎn)是,提供了各種平臺(tái)的支持,解壓后在“Full”目錄中可以看到各個(gè)平臺(tái)的支持。(現(xiàn)在google被各種封殺,如果你打不開(kāi)上面的地址,可以下載我上傳到CSDN的,里面的csharp文件夾就是各個(gè)平臺(tái)的protobuf需要的dll,點(diǎn)擊下載protobuf-net)。
看到里面的unity了嗎,它里面的protobuf-net.dll將是我們準(zhǔn)備用到的。
?
2、為什么有些Protobuf發(fā)布到iOS就用不了,甚至有些在PC都用不了?
a、Protobuf使用了JIT,即在運(yùn)行時(shí)動(dòng)態(tài)編譯,而這個(gè)特性在Unity發(fā)布到iOS時(shí)候是不支持的。因此,會(huì)導(dǎo)致你在PC上可以正常運(yùn)行,發(fā)布到iOS就有問(wèn)題。
b、Protobuf是基于.net 2.0以上框架寫(xiě)的,而Unity僅支持.net 2.0,或者有些使用2.0中比較多的特性,而你在Unity中發(fā)布設(shè)置了.net 2.0的子集。后者你只需要在Player setting中修改設(shè)置就可以了。
上面兩項(xiàng)也可適用于其它第三方類(lèi)庫(kù),如果你自己下載了一個(gè)在PC上或C#里面能正常使用的類(lèi)庫(kù),在U3D里面就不能用了,那么請(qǐng)檢查是否是上面兩條原因?qū)е碌摹?/p>
?
3、手動(dòng)處理C#版本的Protobuf
知道了上面問(wèn)題,我們只要選一個(gè).net2.0的Protobuf,然后它又不是JIT,那就可以正常使用了。
這里用的思路是:
? ? 3.1、創(chuàng)建一個(gè)C#工程,先手動(dòng)創(chuàng)建每一個(gè)要通過(guò)Protobuf序列化或反序列化的數(shù)據(jù)模型類(lèi),然后導(dǎo)出dll
? ? ? ? 以VS為例,首先,創(chuàng)建一個(gè)類(lèi)庫(kù)工程:“文件”>"新建">"項(xiàng)目">"類(lèi)庫(kù)"(記得選擇 .net framework 2.0)
將unity的protobuf的dll添加到項(xiàng)目引用
然后假設(shè)你有一個(gè)類(lèi)WorkerInfo是需要通過(guò)Protobuf進(jìn)行序列化和反序列化的,那么創(chuàng)建一個(gè)WorkerInfo類(lèi),內(nèi)容如下:
?
[csharp]?view plaincopy按下Shift+F6生成dll,在項(xiàng)目的bin\Debug目錄下就可以找到ProtoModelDLL.dll了
?
?
? ? 3.2、創(chuàng)建一個(gè)用于序列化的C#工程,然后運(yùn)行生成dll
? ? ? ? 也是以VS為例,首先創(chuàng)建一個(gè)控制臺(tái)應(yīng)用程序:“文件”>"新建">"項(xiàng)目">"控制臺(tái)應(yīng)用程序"(記得選擇 .net framework 2.0)
將Protobuf和3.1生成的dll添加到引用
在項(xiàng)目生成的Program.cs中寫(xiě)入:
?
[csharp]?view plaincopy
然后ctrl+F5運(yùn)行,這時(shí)候你就可以在bin\Debug中看到ProtoModelSerializer.dll。
?
? ? 3.3、將上面兩個(gè)工程生成的dll(ProtoModelDLL.dll和ProtoModelSerializer.dll)以及protobuf-net.dll拖到unity中
? ? ? ??怎么用?看第4步
4、在Unity中反序列化Protobuf
由于一般游戲客戶端請(qǐng)求的數(shù)據(jù)量比較簡(jiǎn)單,也比較少,因此我們前端請(qǐng)求是不直接二進(jìn)制請(qǐng)求。而前端收到后端返回才采用了Protobuf,因此。這里只討論P(yáng)rotobuf的反序列化。
代碼很簡(jiǎn)單,下面寫(xiě)個(gè)測(cè)試代碼:
?
[csharp]?view plaincopy
?
運(yùn)行后Unity控制臺(tái)輸出了worker的信息。代碼中的dataFromServ字節(jié)數(shù)組的內(nèi)容實(shí)際應(yīng)該是通信時(shí)候后端返回的。這里測(cè)試就不涉及Socket通信的知識(shí)了。
5、服務(wù)端Java也用Protobuf
看到一個(gè)客戶端用Protobuf這么麻煩,那后端會(huì)怎樣呢?其實(shí)后端是比較簡(jiǎn)單的,有Google官方的支持。
下載:https://code.google.com/p/protobuf/downloads/list
下完解壓是這樣的(2.5.0):
進(jìn)入“protobuf-2.5.0\java”文件夾,里面是一個(gè)maven項(xiàng)目,你直接用maven clean install在target目錄就會(huì)生成一個(gè)protobuf-java-2.5.0.jar的jar包了,沒(méi)maven的在這里下載吧,我用maven生成的http://download.csdn.net/detail/kakashi8841/6723689。這個(gè)要時(shí)候?qū)肽愕腏ava項(xiàng)目。就可以了。
然后你寫(xiě)一個(gè)proto文件,調(diào)用“protobuf-2.5.0\src”里面的protoc.exe進(jìn)行生成,它會(huì)幫你生成一個(gè)java文件。(詳細(xì)看https://developers.google.com/protocol-buffers/docs/javatutorial),我這里有提供一個(gè)bat,用于調(diào)用protoc來(lái)生成java文件的,手動(dòng)輸入的話太麻煩了。在windows下把它保存到.bat然后雙擊運(yùn)行就可以了。
?
[vb]?view plaincopy
OK啦,這樣你只要把生成的Java復(fù)制到或直接生成到你的Java項(xiàng)目源碼目錄中,然后就可以使用了。比如:
以前面說(shuō)的WorkerInfo為例
?
?
[java]?view plaincopy
控制臺(tái)就會(huì)輸出:
?
細(xì)心的同學(xué)會(huì)發(fā)現(xiàn)這里的字節(jié)和上面的“8, 233, 7, 16, 100, 24, 1”有點(diǎn)不太一樣。第二個(gè)數(shù)字分別為-23和233.
其實(shí),這個(gè)只是byte的有無(wú)符號(hào)的表示差異而已。
他們的二進(jìn)制表示都是:11101001
?
6、太煩了?!客戶端也要自動(dòng)處理Protobuf
我們看到客戶端沒(méi)加一個(gè)類(lèi),都需要在兩個(gè)VS項(xiàng)目中增加代碼,而后端是直接根據(jù)proto文件生成代碼的。這樣,好像有點(diǎn)不公平,而且這樣前后端還是可能會(huì)寫(xiě)出不一樣的結(jié)構(gòu)。其實(shí)用protobuf我個(gè)人覺(jué)得最大的好處:
? ? a、數(shù)據(jù)量小
? ? b、通過(guò)proto模板生成代碼,減少前后端聯(lián)調(diào)
但是現(xiàn)在只是后端減少了工作,前端并沒(méi)有減少,因此第二個(gè)好處不是很明顯。
那好吧。我沒(méi)有就這樣滿足。因此,我決定,前端也要根據(jù)proto來(lái)生成cs文件。
因此,我使用Java編寫(xiě)了一個(gè)解析Proto文件的工具,并且根據(jù)proto生成cs文件,然后用bat調(diào)用vs的命令行執(zhí)行vs項(xiàng)目的構(gòu)建,最后生成兩個(gè)dll。
我把上面的命令都整合到一個(gè)bat中,因此這個(gè)bat的任務(wù)是:
執(zhí)行java程序,把proto文件生成cs文件。
調(diào)用vs接口構(gòu)建兩個(gè)vs項(xiàng)目,生成兩個(gè)dll。
通過(guò)svn把這兩個(gè)dll提交到客戶端的主干上。
調(diào)用上面根據(jù)proto生成java的bat片段,生成java代碼。
通過(guò)svn把生成的java代碼提交到服務(wù)端主干上。
因此,這樣一來(lái),現(xiàn)在只要編寫(xiě)好proto文件,然后雙擊bat,前后端就都可以通過(guò)更新svn來(lái)獲取最新的Protobuf數(shù)據(jù)對(duì)象。
?
bat運(yùn)行
根據(jù)proto生成cs文件并編譯執(zhí)行兩個(gè)vs項(xiàng)目,然后把生成的dll提交到svn上
生成java代碼并提交svn
這一步相關(guān)操作大家有興趣可以自行試試,有問(wèn)題歡迎在本博客討論。
總結(jié)
以上是生活随笔為你收集整理的Unity3D客户端和Java服务端使用Protobuf的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 对一个程序单元测试
- 下一篇: Java替代C语言的可能性