日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

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

發布時間:2025/3/17 42 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Unity3D客户端和Java服务端使用Protobuf 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

轉自:http://blog.csdn.net/kakashi8841/article/details/17334493

前幾天有位網友問我關于Unity3D里面使用Protobuf的方法,一時有事拖到現在才寫這篇文章,不好意思哈。

本文測試環境:

系統: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、關于Protobuf的C#實現

2、為什么有些Protobuf發布到iOS就用不了,甚至有些在PC都用不了?

3、手動處理C#版本的Protobuf

?

? ? 3.1、創建一個C#工程,先手動創建每一個要通過Protobuf序列化或反序列化的數據模型類,然后導出dll

? ? 3.2、創建一個用于序列化的C#工程,然后運行生成dll

? ? 3.3、將上面兩個工程生成的dll拖到unity中

4、在Unity中反序列化Protobuf

5、服務端Java也用Protobuf

6、太煩了?!客戶端也要自動處理Protobuf

?

1、關于Protobuf的C#實現

首先,U3D里面Protobuf使用的是C#的實現,那么目前有幾個可選的C#實現:

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?這里下載到他的代碼和工具),它比較好的一點是,提供了各種平臺的支持,解壓后在“Full”目錄中可以看到各個平臺的支持。(現在google被各種封殺,如果你打不開上面的地址,可以下載我上傳到CSDN的,里面的csharp文件夾就是各個平臺的protobuf需要的dll,點擊下載protobuf-net)。

看到里面的unity了嗎,它里面的protobuf-net.dll將是我們準備用到的。

?

2、為什么有些Protobuf發布到iOS就用不了,甚至有些在PC都用不了?

a、Protobuf使用了JIT,即在運行時動態編譯,而這個特性在Unity發布到iOS時候是不支持的。因此,會導致你在PC上可以正常運行,發布到iOS就有問題。

b、Protobuf是基于.net 2.0以上框架寫的,而Unity僅支持.net 2.0,或者有些使用2.0中比較多的特性,而你在Unity中發布設置了.net 2.0的子集。后者你只需要在Player setting中修改設置就可以了。

上面兩項也可適用于其它第三方類庫,如果你自己下載了一個在PC上或C#里面能正常使用的類庫,在U3D里面就不能用了,那么請檢查是否是上面兩條原因導致的。

?

3、手動處理C#版本的Protobuf

知道了上面問題,我們只要選一個.net2.0的Protobuf,然后它又不是JIT,那就可以正常使用了。

這里用的思路是:

? ? 3.1、創建一個C#工程,先手動創建每一個要通過Protobuf序列化或反序列化的數據模型類,然后導出dll

? ? ? ? 以VS為例,首先,創建一個類庫工程:“文件”>"新建">"項目">"類庫"(記得選擇 .net framework 2.0)

將unity的protobuf的dll添加到項目引用

然后假設你有一個類WorkerInfo是需要通過Protobuf進行序列化和反序列化的,那么創建一個WorkerInfo類,內容如下:

?

[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,在項目的bin\Debug目錄下就可以找到ProtoModelDLL.dll了

    ?

    ?

    ? ? 3.2、創建一個用于序列化的C#工程,然后運行生成dll
    ? ? ? ? 也是以VS為例,首先創建一個控制臺應用程序:“文件”>"新建">"項目">"控制臺應用程序"(記得選擇 .net framework 2.0)

    將Protobuf和3.1生成的dll添加到引用

    在項目生成的Program.cs中寫入:

    ?

    [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運行,這時候你就可以在bin\Debug中看到ProtoModelSerializer.dll。

    ?

    ? ? 3.3、將上面兩個工程生成的dll(ProtoModelDLL.dll和ProtoModelSerializer.dll)以及protobuf-net.dll拖到unity中

    ? ? ? ??怎么用?看第4步

    4、在Unity中反序列化Protobuf

    由于一般游戲客戶端請求的數據量比較簡單,也比較少,因此我們前端請求是不直接二進制請求。而前端收到后端返回才采用了Protobuf,因此。這里只討論Protobuf的反序列化。

    代碼很簡單,下面寫個測試代碼:

    ?

    [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);??
  • ????}??
  • }??
  • ?

    運行后Unity控制臺輸出了worker的信息。代碼中的dataFromServ字節數組的內容實際應該是通信時候后端返回的。這里測試就不涉及Socket通信的知識了。

    5、服務端Java也用Protobuf

    看到一個客戶端用Protobuf這么麻煩,那后端會怎樣呢?其實后端是比較簡單的,有Google官方的支持。

    下載:https://code.google.com/p/protobuf/downloads/list

    下完解壓是這樣的(2.5.0):

    進入“protobuf-2.5.0\java”文件夾,里面是一個maven項目,你直接用maven clean install在target目錄就會生成一個protobuf-java-2.5.0.jar的jar包了,沒maven的在這里下載吧,我用maven生成的http://download.csdn.net/detail/kakashi8841/6723689。這個要時候導入你的Java項目。就可以了。

    然后你寫一個proto文件,調用“protobuf-2.5.0\src”里面的protoc.exe進行生成,它會幫你生成一個java文件。(詳細看https://developers.google.com/protocol-buffers/docs/javatutorial),我這里有提供一個bat,用于調用protoc來生成java文件的,手動輸入的話太麻煩了。在windows下把它保存到.bat然后雙擊運行就可以了。

    ?

    [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復制到或直接生成到你的Java項目源碼目錄中,然后就可以使用了。比如:
    以前面說的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));??
  • ????}??
  • }??

  • 控制臺就會輸出:

    ?

    細心的同學會發現這里的字節和上面的“8, 233, 7, 16, 100, 24, 1”有點不太一樣。第二個數字分別為-23和233.

    其實,這個只是byte的有無符號的表示差異而已。

    他們的二進制表示都是:11101001

    ?

    6、太煩了?!客戶端也要自動處理Protobuf

    我們看到客戶端沒加一個類,都需要在兩個VS項目中增加代碼,而后端是直接根據proto文件生成代碼的。這樣,好像有點不公平,而且這樣前后端還是可能會寫出不一樣的結構。其實用protobuf我個人覺得最大的好處:

    ? ? a、數據量小

    ? ? b、通過proto模板生成代碼,減少前后端聯調

    但是現在只是后端減少了工作,前端并沒有減少,因此第二個好處不是很明顯。

    那好吧。我沒有就這樣滿足。因此,我決定,前端也要根據proto來生成cs文件。

    因此,我使用Java編寫了一個解析Proto文件的工具,并且根據proto生成cs文件,然后用bat調用vs的命令行執行vs項目的構建,最后生成兩個dll。

    我把上面的命令都整合到一個bat中,因此這個bat的任務是:

    執行java程序,把proto文件生成cs文件。

    調用vs接口構建兩個vs項目,生成兩個dll。

    通過svn把這兩個dll提交到客戶端的主干上。

    調用上面根據proto生成java的bat片段,生成java代碼。

    通過svn把生成的java代碼提交到服務端主干上。

    因此,這樣一來,現在只要編寫好proto文件,然后雙擊bat,前后端就都可以通過更新svn來獲取最新的Protobuf數據對象。

    ?

    bat運行

    根據proto生成cs文件并編譯執行兩個vs項目,然后把生成的dll提交到svn上

    生成java代碼并提交svn

    這一步相關操作大家有興趣可以自行試試,有問題歡迎在本博客討論。

    總結

    以上是生活随笔為你收集整理的Unity3D客户端和Java服务端使用Protobuf的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。