如何为 Unity3d 设计我的在线游戏服务器?
最近一直在unity3d做多人游戏开发.我对 Unity 的 MasterServer 如何统一工作有了一个很好的了解.
但现在我想从头开始制作自己的游戏服务器.我研究并知道我们可以使用谷歌云计算和应用引擎来制作我们自己的匹配服务器和游戏主机服务器.
但我完全不知道我们如何开始对我的服务器进行编码.我们是否使用简单的 http 请求和 json 结果来做到这一点?或者是否有任何其他技术也可以实时处理 FPS 类型的游戏.我认为发送 http 请求并等待它的结果可能不够快,无法在每秒发送超过 100 条数据的 FPS 类型游戏中工作.
起初我想编写 php 脚本并将其托管到某个 url,然后向该 url 发送请求并等待它的响应.但我发现,如果我使用这个过程,那么仅仅从服务器获得一个响应至少需要 0.5 秒或更长时间.在这种情况下,游戏会有很多延迟.
我知道游戏服务器在某种 tcp 或 udp 网络上工作.但我的问题是,我应该为服务器制作什么样的应用程序来接收这些数据并快速发送处理结果.
Recently, I have been doing multiplayer game development in unity3d. I have got the pretty good idea of how the Unity's MasterServer works in unity.
But now I want to make my own game server from scratch. I researched and got to know that we can use the Google cloud compute and the app engine for making our own matchmaking server and the game host server.
But I am totally clueless how do we start doing coding my server. Do we do it using simple http request and json result? Or is there any other technique that can in real time work with FPS type games also. I dont think that the sending http requests and waiting for it result can be fast enough to work in a FPS type games where every seconds we send more than 100s of datas.
At first I thought of writing php scripts and hosting it to some url, and then sending request to that url and wait for its response. But I found out that if I use this process then for just getting one response from the server it would take me atleast 0.5 seconds or more. In this condition, there would be a lot of lag in game.
I know that game servers work on some kind of tcp or udp networking. But my question is this that what kind of application shall I make for the server to receive these datas and send the processed results fast.
推荐答案
首先,我认为您将 MasterServer 与在游戏过程中发送和接收游戏数据所需的连接混淆了.
First of all I think that you are confusing MasterServer with the connection required to send and receive game data during gameplay.
MasterServer 用于检索创建游戏的服务器的信息,例如 IP 地址和端口号.获取 IP 和端口号后,客户端可以使用这些信息直接连接到服务器.
MasterServer is used to retrieve the information of the server that created the game such as IP Address and port number. After you retrieve the IP and port number, the client can directly connect to the server with these information.
我们使用简单的http请求和json结果吗?
Do we do it using simple http request and json result?
对于 MasterServer,是的,您可以.您还可以将它与 PHP 结合使用,将游戏会话保存在数据库中.
For MasterServer, yes you can. You can also use it in combination with PHP to save game sessions on the database.
例如,当玩家想要创建一个新游戏时,你把他们的游戏信息,如游戏名称、密码、最大玩家数、玩家的 ip 地址、端口号,然后将其序列化为 json 并使用 RESTful 发送.
For example, when player wants to create a new game, you take you take their game information such as game name, password, max players, player's ip address, port number then serialize it to json and send using RESTful.
您可以使用 PHP 接收该游戏信息并将其存储到服务器中,以便其他玩家可以找到它.
You can use PHP to receive that game information and store it into server so that other players can find it.
这不应该影响性能,因为您只使用它来创建、查询和销毁游戏季节.您没有在玩游戏期间使用它来发送游戏数据.
This shouldn't affect performance since you only using it to create, query and destroy game seasons. You are not using it to send game data during game play.
至于在游戏过程中发送数据,您可以使用原始套接字来执行此操作.使用 C# 的 TCP 或 UDP.如果您想获得最大的性能,请使用 C++ 进行本地化,因为 Unity 的 UNet 是用 C++ 编写的.大多数 FPS 服务器都是用 C++ 编写的,这是为了确保它们获得有史以来的最高性能.
As for sending data during gameplay, you do this with raw socket. Either TCP or UDP with C#. Go native with C++ with if you want to get the maximum performance sine Unity's UNet is written in C++. Most FPS server's are written in C++ and this is to make sure that they get the maximum performance ever.
请记住,服务器有很多种类型,因此我无法在本文中介绍所有类型.我将只关注 MasterServer,它告诉客户端创建的游戏的 IP 地址,然后是当玩家之间无法建立直接连接时使用的中继.
Remember there are many types of servers so I can't cover all of them in this post. I will just focus on MasterServer which tells client the IP addresses on Games created then Relay which is used when direct connection between players cannot be established.
我建议您使用 Google 的 Protobuf 而不是 Json,因为它的性能和轻量级.如果您发现任何比 Protobuf 更快的序列化 API,请使用它.
I suggest you use Google's Protobuf over Json for its performance and lightweight. If you find any serialization API that's faster than Protobuf then use it.
直接连接:
服务器:
1.使用 Nat 执行 端口转发.
1.Use Nat to perform port forwarding.
2.通过创建 TCP/UDP 服务器.
3.将游戏信息(游戏名称、ip、端口号)发送到MasterServer.
3.Send the Game Info(game name, ip, port number) to the MasterServer.
4.当客户端连接到该信息时,通过使用 Protobuf send 序列化数据(FPS 玩家位置?)开始向客户端发送数据.
4.When client connects with that information, start sending data by serializing the data(FPS player position?) with Protobuf send, to client.
5.当您从客户端接收数据时,使用 Protobuf 对其进行反序列化.
5.When you receive data from the client, deserialize it with Protobuf.
客户:
1.连接到 MasterServer 并检索正在运行的游戏信息.
1.Connect to the MasterServer and retrieve running Game Informations.
2.创建一个TCP/UDP 客户端 并连接到 IP 和端口号之一.
2.Create a TCP/UDP client and connect to one of the IP and port number.
要发送和接收数据,请使用服务器 #4 和 #5 中的步骤.
To send and receive data, use steps from Server #4 and #5.
有时,端口转发在某些设备上不起作用.在这种情况下,具有不同全局 IP 地址的两个玩家无法连接在一起,这就是中继和 C++ 发挥作用的地方.中继应该不使用 http 请求、json 或 php 完成.它应该使用 C++ 或类似的快速语言,如 python.
Sometimes, port forwarding won't work on some devices. In that case, two players with different global IP Addresses cannot connect together and this is where a relay and C++ comes into play. The relay should not be done with http requests, json or php. It should be made with C++ or some similar fast language such as python.
同样,有很多方法可以做到这一点.最简单的方法是为每个创建的游戏生成一个私钥.当服务器/客户端相互发送数据时,它们必须在该数据中包含此密钥,并且此密钥将用于确定中继服务器应将数据发送给谁.
Again, there are many ways to do this. The easiest way is to generate a private key for each game that is created. When server/client send data to one another, they must include this key in that data and this key will be used to determine who the relay server should send the data to.
与中继的连接:
服务器:
1.通过连接将游戏信息(游戏名称)发送到MasterServer来创建游戏.
1.Create Game by connecting to sending the Game Info(game name) to the MasterServer.
2.MasterServer通过生成私钥并将其返回给服务器来响应.
2.MasterServer responds by generating a private key and returning it to the Server.
3.使用该私钥连接到中继服务器.
3.Connect to the relay server with that private key.
4.要向其他玩家发送数据,请使用 Protobuf 序列化数据(FPS 玩家位置?),然后发送到 Relay 服务器.该数据还必须包含私钥.
4.To send data to other players, serialize the data(FPS player position?) with Protobuf then send to the Relay server. That data must also contain the private key.
5.中继服务器从该服务器接收数据,读取私钥并将数据转发/发送到具有相同私钥的任何其他客户端.
5.Relay server receives data from this server, reads the private key and forward/send the data to any other client with the-same private key.
6.当您从 Relay 服务器接收到其他玩家发送的数据时,使用 Protobuf 对其进行反序列化.
6.When you receive data from the Relay server that the other player sent, deserialize it with Protobuf.
从 #4 重复到 #6,只要连接仍然存在且游戏仍未结束.
Repeat from #4 to #6 as long as the connection is still alive and game is still not over.
客户:
1.连接到 MasterServer 并检索正在运行的游戏信息.
1.Connect to the MasterServer and retrieve running Game Informations.
2.MasterServer通过将该游戏的私钥返回给客户端来响应.
2.MasterServer responds by returning a private key of that game to the client.
3.使用该私钥连接到中继服务器.
3.Connect to the relay server with that private key.
4.要向其他玩家发送数据,请使用 Protobuf 序列化数据(FPS 玩家位置?)然后发送到 Relay 服务器.该数据还必须包含私钥.
4.To send data to other players, serialize the data(FPS player position?) with Protobuf then send to the Relay server. That data must also contain the private key.
5.中继服务器从该服务器接收数据,读取私钥并将数据转发/发送到具有相同私钥的任何其他客户端.
5.Relay server receives data from this server, reads the private key and forward/send the data to any other client with the-same private key.
6.当您从 Relay 服务器接收到其他玩家发送的数据时,使用 Protobuf 对其进行反序列化.
6.When you receive data from the Relay server that the other player sent, deserialize it with Protobuf.
从 #4 重复到 #6,只要连接仍然存在且游戏仍未结束.
Repeat from #4 to #6 as long as the connection is still alive and game is still not over.
相关文章