2017-03-05 27 views
1

我目前正在为Unity游戏构建我自己的网络代码(用于学习体验),而且我正在对事情的“解码数据包”方面发生严重的延迟。在多人游戏中,如何有效地通过套接字发送位置数据?

基本上,我有playerObject将位置数据(Vector3(x,y,z))作为JSON字符串发送到服务器,服务器将其发回给所有其他玩家。

东西的插座边很漂亮。从创建数据包到收到数据包时的延迟非常小。

但我上午让我的客户一个巨大的延迟,当他们试图取消JSON的远程客户端的位置:

Vector3 remotePos = JsonUtility.FromJson<Vector3>(_command.Substring(5 + _usernameLength));

JSON字符串有字符串的开头的标识符说它是一个位置更新,然后是两个数字,表示用户名的长度,然后是用户名(以便远程客户端可以更新正确的playerObject。整个字符串看起来是这样的)

POS09NewPlayer{"x":140.47999572753907,"y":0.25,"z":140.7100067138672}

从服务器接收这样的报文后,我的客户将瓶坯以下任务:

 int _usernameLength = Int32.Parse(_command.Substring(3, 2)); 
     string _username = _command.Substring(5, _usernameLength); 
     Vector3 remotePos = JsonUtility.FromJson<Vector3> 
     if (_username != username) 
     { 
     playerDict[_username].transform.position = remotePos; 
     } 

所有这些“作品”,但变得非常低迷后刚刚3个客户端同时连接。

我在做什么错?必须有一个重大的缺陷,因为我每3秒钟只发送0.015秒的更新时间,而像“战地”这样的游戏每秒可以发送60次更新给64名玩家!

任何意见,将不胜感激。

+1

至少举动'JsonUtility.FromJson'在'if' –

+0

我很怀疑反序列化JSON在这种情况下,造成这种巨大的影响 – Evk

+0

@Evk我指望收到的数据包,同时计数json'd包。我接收数据包的速度是我能够快速发送的速度的三倍。这意味着东西落后。 – MrDysprosium

回答

5

那么,确实有优化的空间。既然你引述的大游戏引擎作为参考,我会根据旧的虚幻引擎版本和一些他们使用的优化给你一些例子:

  • 网络包使用UDP协议。它仍然需要自行处理掉落,重复或无序的软件包,但它会吞下那颗苦药,而不是使用实际的TCP连接,因为后者会带来更多的开销。
  • 服务器会跟踪它发送给客户端的信息更新。对于客户端上由服务器复制的每个对象,服务器都会跟踪所有变量。在每次游戏循环更新结束时,服务器将检查哪些变量实际上具有与上次向客户端发送更新时不同的值。只有实际存在差异时,才会将新值发送给客户端。这可能看起来像一个令人难以置信的开销,但网络带宽是一个比系统内存和CPU时间更稀缺的资源。
  • 矢量信息在通过网络发送之前实际上被截断。该引擎使用float作为其向量分量的数据类型,但它仍然将X,Y和Z四舍五入为最接近的整数,并将其传递为完整的浮点数据。这样它们只占用几位到几个字节,而不是12个字节的未压缩原始浮点数。
  • 在客户端模拟位置更新并与来自服务器的传入数据合并。为避免位置更新抖动,客户端根据其速度值预测对象的新位置。当客户端稍后从服务器接收到位置更新时,它将优雅地将对象略微移动到新的位置(基本上是客户端和服务器坐标之间的折衷),并且只有在服务器的位置与客户端版本。这是用很多东西来完成的。如果玩家发射了弹丸,那么在服务器上执行该弹丸,这将产生弹丸并将其发送给玩家以更新其位置。但是玩家也会收到关于镜头的函数调用,并且在本地创建子弹并更新其弹道。即使该抛射物不能真正杀死客户端的玩家,它的轨迹和效果仍然可以在本地模拟以给出游戏流畅的印象。如果碰到什么东西,可以在该位置播放适当的效果,而不需要服务器告诉客户端创建这些效果。
  • 服务器记录每个玩家的相关内容。如果一名玩家位于地图的另一边,并且不需要向您发送关于该玩家动作的任何更新信息。如果该玩家的投掷物后来碰巧出现在你的视线中,服务器仍然可以在适当的时候告诉你这些投射物。

整个事情比我可以在这篇文章中填入的内容要复杂得多,但其要点可能是:网络带宽是多人游戏中最有限的资源,因此引擎不再使用它发送尽可能少且很少的信息包的方式。

注意事项?在此引擎中,对于整个矢量而言,小于您的位置矢量的单个分量已经被认为太大。我猜JSON真的在这里引入了一些开销,只是由于它的冗长。你可以发送数字作为字符串,当你也可以发送他们的实际位并从实际包装中推断出它们的含义时。

+0

哇,谢谢你写了很多有用的信息。 你能否详细介绍一下最后一部分? “你也可以只是发送他们的实际数据,并从实际包装中推断出他们的含义。” – MrDysprosium

+0

这更多的是暗示实际的引擎可能会这样做,因为它们可能不使用JSON。如果你使用UDP作为准系统,你可以随意发送你想要的任何字节(每个包最多大约65000字节)。然后,您可以用几个字节来识别播放器,其中一些用于识别发送的数据,然后用几个字节来表示矢量的实际数值,然后在客户端自行解析。在.NET中的UDP示例:https://social.msdn.microsoft.com/Forums/zh-CN/92846ccb-fad3-469a-baf7-bb153ce2d82b/simple-udp-example-code?forum=netfxnetcom –

+0

保留但请注意,UDP不会自行处理重复,丢弃或乱序的包,因此您可能需要自行处理。这意味着发送某种形式的确认,表明已收到包裹,否则请发件人定期重新发送包裹,直至收到确认信息。并且对传出包进行时间戳记,所以如果较新的数据事先到达(但仍然发送确认,以便发送者不继续发送这些包),旧数据可以在接收端丢弃。 –

相关问题