日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > java >内容正文

java

Unity3D客户端和Java服务端使用Protobuf

發(fā)布時(shí)間:2025/3/17 java 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Unity3D客户端和Java服务端使用Protobuf 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

轉(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
  • using?System;??
  • using?System.Collections.Generic;??
  • using?System.Text;??
  • using?ProtoBuf;??
  • namespace?Com.YourCompany.Project.Proto.Module{??
  • ????[ProtoContract]??
  • ????public?class?WorkerInfo?{???
  • ??
  • ??
  • ????????[ProtoMember(1)]??
  • ????????public?int?workerId;??
  • ??
  • ??
  • ????????[ProtoMember(2)]??
  • ????????public?int?leftClosingTimeSec;??
  • ??
  • ??
  • ????????[ProtoMember(3)]??
  • ????????public?int?buildingId;??
  • ??
  • ??
  • ????}??
  • }??
  • 按下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
  • using?System;??
  • using?System.Collections.Generic;??
  • using?System.Text;??
  • using?ProtoBuf.Meta;??
  • using?ProtoBuf;??
  • using?ProtoBuf.Compiler;??
  • using?Com.YourCompany.Project.Proto.Module;??
  • ??
  • ??
  • namespace?ProtoModelSerializerCreator??
  • {??
  • ????class?Program??
  • ????{??
  • ????????static?void?Main(string[]?args)??
  • ????????{??
  • ????????????var?model?=?TypeModel.Create();??
  • ??
  • ????????????model.Add(typeof(object),?true);??
  • ????????????model.Add(typeof(WorkerInfo),?true);??
  • ??
  • ????????????model.AllowParseableTypes?=?true;??
  • ????????????model.AutoAddMissingTypes?=?true;??
  • ????????????model.Compile("ProtoModelSerializer",?"ProtoModelSerializer.dll");??
  • ????????}??
  • ????}??
  • }??

  • 然后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
  • using?UnityEngine;??
  • using?System.Collections;??
  • using?ProtoBuf.Meta;??
  • using?Com.YourCompany.Project.Proto.Module;??
  • using?System.IO;??
  • using?Com.Duoyu001.Proto.Building;??
  • using?Com.Duoyu001.Proto.Worker;??
  • ??
  • public?class?TestProto?:?MonoBehaviour??
  • {??
  • ??
  • ????//?init??
  • ????void?Start?()??
  • ????{??
  • ????????byte[]?dataFromServ?=?new?byte[]{8,?233,?7,?16,?100,?24,?1};????//these?bytes?are?generated?by?server??
  • ??????????
  • ????????RuntimeTypeModel?serializer?=?ProtoModelSerializer.Create?();??
  • ????????System.IO.MemoryStream?memStream?=?new?System.IO.MemoryStream?();??
  • ????????WorkerInfo?w?=?new?WorkerInfo?();??
  • ????????serializer.Deserialize?(memStream,?w,?w.GetType?());????//asign?value?to?proto?model??
  • ??????????
  • ????????Debug.Log?(w.workerId?+?",?"?+?w.buildingId?+?",?"?+?w.leftClosingTimeSec);??
  • ????}??
  • }??
  • ?

    運(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
  • @echo?off??
  • echo?**?setting?runtime?variable??
  • ??
  • REM?_protoSrc?是你的proto文件目錄的位置??
  • set?_protoSrc=F:\project_proto_src\trunk\xgame-controllers\protos??
  • ??
  • REM?protoExe?是用于從proto生成java的protoc.exe程序的位置??
  • set?protoExe=C:\Users\john\Desktop\protobuf-2.5.0\src\protoc.exe??
  • ??
  • REM?java_out_file?存放生成的Java文件目錄的位置??
  • set?java_out_file=F:\project_proto_src\trunk\xgame-controllers\src\main\java\??
  • ??
  • for?/R?"%_protoSrc%"?%%i?in?(*)?do?(???
  • ????set?filename=%%~nxi???
  • ????if?"%%~xi"??==?".proto"?(??
  • ????????%protoExe%?--proto_path=%_protoSrc%?--java_out=%java_out_file%?%%i??
  • ????)??
  • )??

  • OK啦,這樣你只要把生成的Java復(fù)制到或直接生成到你的Java項(xiàng)目源碼目錄中,然后就可以使用了。比如:
    以前面說(shuō)的WorkerInfo為例

    ?

    ?

    [java]?view plaincopy
  • package?com.duoyu001.xgame;??
  • ??
  • import?java.util.Arrays;??
  • ??
  • import?com.duoyu001.xgame.worker.proto.WorkerInfoBuilder.WorkerInfo;??
  • ??
  • public?class?TestProto?{??
  • ??
  • ????public?static?void?main(String[]?args)?{??
  • ????????WorkerInfo?w?=?WorkerInfo.newBuilder().setBuildingId(1)??
  • ????????????????.setLeftClosingTimeSec(100).setWorkerId(1001).build();??
  • ????????byte[]?byteArray?=?w.toByteArray();??
  • ????????System.out.println(Arrays.toString(byteArray));??
  • ????}??
  • }??

  • 控制臺(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)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。