最近公司的一个unity项目要把通信方式从Photon替换成grpc,正好系统学一下grpc,以下是我的学习心得。
本篇博客系统详细地介绍了unity使用grpc通信的全部要点,希望可以帮助到大家。奥利给!
grpc+protobuf+unity+C#
一、本篇博客知识点简介
看了这篇博客能获得以下技术知识;
- 定义服务
- 使用GRPC.Tools自动代码,把.proto解析成.cs
- 创建服务端及客户端
- 在C#中使用Grpc
- 在Unity中使用Grpc
二、资源及工具的下载地址
1、protocolBuffers各个版本
下载地址:https://github.com/protocolbuffers/protobuf
protoBuf版本有很多,项目中的.proto用的哪个版本,就下载哪个版本解析,无要求的话建议下载3.8.x,因为目前Grpc C#对Unity仍是实验性支持,所用的版本就是3.8。
按照下图选项下载:
然后找个文档存下来,解压:
Protocol buffers是一个灵活的、高效的、自动化的用于对结构化数据进行序列化的协议,与XML相比,Protocol buffers序列化后的码流更小、速度更快、操作更简单。
(要与Protocol区分开,Protocol为进行网络中的数据交换而建立的规则、标准或约定,是控制两实体间数据交换的一套规则。)
你只需要将要被序列化的数据结构定义一次(使用.proto文件定义),便可以使用特别生成的源代码(使用protobuf提供的生成工具)轻松的使用不同的数据流完成对这些结构数据的读写操作,即使你使用不同的语言(protobuf的跨语言支持特性)
本篇博客只是介绍如何使用protocolBuffers,如果想详细了解原理可看此博客:传送门
2、GRPC
GRPC是一个高性能、开源和通用的 RPC (远程过程调用协议)框架,基于ProtoBuf(ProtocolBuffers)序列化协议开发,且支持众多开发语言。
下载地址:https://github.com/grpc/grpc
同样找个文档存下来,解压。此时我们下载的是grpc对应的所有平台,C#和unity的官方案例在此路径下:
3、grpc_unity_package.2.27.0-dev
为了方便快捷的实现untiy网络通信,grpc直接提供了unity通信所需的.dll(其中包含的Google.protobuf 版本是3.8),下载后可以直接放入unity的plugins文件夹下供接口引用。
4、.NET Core SDK 2.1及以上
在使用grpc和protobuf时,电脑环境需要是.NET Core SDK 2.1及以上,根据自己的vs版本下载对应的sdk和Runtime,下载后是.exe,双击安装就可以了。
当然,除此之外,你肯定得装有VisualStudio和unity相应版本
.
三、C#使用Grpc方法流程
1、新建项目
然后在当前解决方案下,添加两个控制台应用程序 grpcServer 、grpcClient。
新建后的解决方案如下:
2、定义服务
定义服务,即使用proto语法编写接口,调用grpc。这里我们在 grpcTest 项目里添加一个 .proto脚本,用于解析成 .cs 。
点击添加 -> 新建项目 ,在名称中直接填写:test.proto,内容如下,复制到脚本中。
syntax ="proto3";
packagegrpcTesst;
servicegRPC {
rpc SayHello (TestRequest) returns(TestReply) {}
}
messageTestRequest {
string name = 1;
}
messageTestReply {
string message = 1;
}
test.proto文件最好放到此目录下,方便初学者直接使用我给的命令行(目前你还没有test.cs和testGrpc.cs)。
关于grpc的详细方法,如果想了解有gRPC 官方文档中文版 : http://doc.oschina.net/grpc?t=60132,
也可以参考此博客:https://blog.csdn.net/qq_28110727/article/details/78984746
.
3、使用GRPC.Tools自动生成.cs代码
上一步服务定义成功了,接下来在项目中导入相关的包,然后使用GRPC.Tools把test.pproto自动解析成.cs代码。
1、在每个项目中(grpctest、grpcServer 、grpcClient)添加上Grpc 及 Google.Protobuf
NuGet 命令行(视图-> 其他窗口 -> 程序包管理器控制台):
Install-Package Grpc
Install-Package Google.Protobuf
输入NuGet 命令行,回车。
此处可以直接切换项目
2、 然后在 grpcTest 项目中再添加上工具 Grpc.Tools(要生成源文件)
Install-Package Grpc.Tools
3、接下来使用GRPC.Tools把test.proto自动解析成.cs代码
上部操作完以后,可以看到各种包体都导入到了grpcTest\packages文件夹中,注意一下Grpc.Tools.的版本,我的是Grpc.Tools.2.32.0。
在系统中运行cmd,cd 指令进入到我们的工程文件夹里,也就是packages的上一层,然后编写以下指令并运行。
(Grpc.Tools的版本号、项目名grpcTest、test.proto 都要换成你自己工程中相应的名字)。
packages\Grpc.Tools.2.32.0\tools\windows_x86\protoc.exe -IgrpcTest --csharp_out grpcTest grpcTest\test.proto --grpc_out grpcTest --plugin=protoc-gen-grpc=packages\Grpc.Tools.2.32.0\tools\windows_x86\grpc_csharp_plugin.exe
输入命令,回车,可以发现在grpcTest\grpcTest目录下多出了test.cs和testGrpc.cs两个类,这就是test.proto解析出来的.cs代码,里面包含了客户端调用的接口。
4、将生成的类加入项目,添加引用
现在将Test.cs 及 TestGrpc.cs 类包含至grpcTest 项目。
项目上右键-> 添加-> 现有项 选择Test.cs 及 TestGrpc.cs文件
添加后如下:
然后 grpcServer、 grpcClient 分别都引用 grpcTest 。
( 项目引用节点上 右键-> 添加引用-> 项目 解决方案 下 选择项目 确定 )
如下,引用添加成功。
4、创建服务端及客户端
下面我们来编写服务端及客户端。
1、服务端:
将默认 Program.cs 文件 按F2 重命名 为 TestServer.cs (注: 在 解决方案面板上操作,会提示 是否同时修改相关的引用, 选择是!)
usingGrpc.Core;
usingGrpcTesst;
usingSystem;
usingSystem.Threading.Tasks;
namespacegrpcServer
{
class gRPCImpl : gRPC.gRPCBase
{
// 实现SayHello方法
public override Task<TestReply>SayHello(TestRequest request, ServerCallContext context)
{
return Task.FromResult(newTestReply { Message = "Hello " + request.Name });
}
}
class TestServer
{
const int Port = 9007;
public static void Main(string[] args)
{
Server server = new Server
{
Services= { gRPC.BindService(new gRPCImpl()) },
Ports = { newServerPort("localhost", Port, ServerCredentials.Insecure) }
};
server.Start();
Console.WriteLine("gRPC serverlistening on port " + Port);
Console.WriteLine("任意键退出...");
Console.ReadKey();
server.ShutdownAsync().Wait();
}
}
}
2、客户端:
将默认 Program.cs 文件 按F2 重命名 为 TestClient.cs (注: 在 解决方案面板上操作,会提示 是否同时修改相关的引用, 选择是!)
usingGrpc.Core;
usingGrpcTesst;
usingSystem;
namespacegrpcClient
{
class TestClient
{
static void Main(string[] args)
{
Channel channel = newChannel("127.0.0.1:9007", ChannelCredentials.Insecure);
var client = newgRPC.gRPCClient(channel);
var reply = client.SayHello(newTestRequest { Name = "sunguangdong" });
Console.WriteLine("来自" +reply.Message);
channel.ShutdownAsync().Wait();
Console.WriteLine("任意键退出...");
Console.ReadKey();
}
}
}
5、实现grpc通信
上步操作创建了客户端和服务端,接下来就可以尝试通信了。
1、在这两个项目上右键 生成。
生成以后会看到项目的此目录下多了两个.exe
(grpcClient\bin\Debug\grpcClient.exe)
(grpcServer\bin\Debug\grpcServer.exe)
先双击执行grpcServer.exe,开启本地服务器,然后再执行grpcClient.exe客户端,如下图所示成功进行通信了。
四、在Unity中使用Grpc
方法1 导入生成的.cs
1,创建空的Unity工程,在File -> Build Settings -> Player Settings中把Api Compatibility Level(老版本叫Script Runtime Version)设为 .NET 4.x
3,将之前下载的grpc_unity_package.zip解压到Assets目录下,即Plugins文件夹。
4,上一步grpcTest项目生成的Test.cs 及 TestGrpc.cs 复制到Assets某个文件夹下
5,新建脚本GrpcTest.cs挂在场景中任意GameObject,在Start()方法中添加代码,引入grpc等相关库,运行游戏。
using Grpc.Core;
using GrpcTest;
void Start()
{
Channel channel = new Channel("127.0.0.1:9007", ChannelCredentials.Insecure);
var client = new gRPC.gRPCClient(channel);
var reply = client.SayHello(new TestRequest { Name = "sunguangdong" });
print("Greeting: " + reply.Message);
channel.ShutdownAsync().Wait();
}
方法2 导入生成的.dll
前3步和方法1 一样,第4步:
在VS中右击解决方案,生成解决方案。可以在grpcTest项目文件夹此路径下找到生成的grpcTest.dll。
grpcTest\grpcTest\bin\Debug\grpcTest.dll
复制此文件,粘贴到unity工程的plugins文件夹下,接下来和方法 1的第5步一样操作。
当然了,你也可以直接使用grpc官方提供的unity案例,在之前下载的grpc文件的此目录下:
grpc-master\examples\csharp\HelloworldUnity
五、注意事项及报错解决办法
1、Google.Protobuf版本不一致,如下报错提示:
因为grpc提供的unity案例用的是Google.Protobuf 3.8.0,所以如果我们想直接用官方给的plugins,就需要在vs中使用相同的版本,在vs中导入包体时,直接使用提前下载好的protoBuf 3.8.0:
打开grpcTest项目中的引用,可以查看版本:
右击移除:
然后添加引用,手动指定路径,因为语言是C#,所以选择csharp,路径如下
protobuf-3.8.x\csharp\src\Google.Protobuf\bin\Debug\net45
替换引用后,重新解析test.proto,生成Test.cs 及 TestGrpc.cs 或者grpcTest.dll。
2、端口问题
以上案例连接的均是本地服务器,如果连接云服务器或者远程服务器,记得端口号不能错.