不同类型的游戏对带宽的要求也是不一样的。
首先假设我们的游戏是mmo类型,使用的是状态同步,同步间隔是50ms(一秒同步20次),主要同步的内容包括坐标、朝向、动画状态。我们可以估算一下每秒每个客户端需要向服务器上传的数据量
坐标:xyz,float类型,共计3*4byte = 12byte 朝向:y,float类型,共计4byte 动画:假设需要同步4个(int/float)参数,共计4*4byte = 16byte 每次上传的数据为 12+4+16=32byte,每秒上传20次,所有每秒上传20*32byte = 640byte。
实际上每个数据包也会带上协议类型、包的总长度等,要略大于上面的计算结果,如果我们使用了protobuf,它会对数据进行一定的压缩,这里采取的是估算所以就按每秒上传640byte。一个玩家一秒上传的数据要同步到其他玩家需要的流量是(玩家数量-1)* 640byte,比如比如同时有10个人在线,那一个玩家所占服务器是上行流量是(10-1)* 640byte = 5760byte。十个玩家共占服务器上行流量=10 * 5760byte=56.25KB。通过上面的推导可以得出公式(n-1) * 640 * n = 128 * 1024,算出n=14.8196 。这样看来一个1M带宽的服务器最多只能14个人同时在线。
我们接着分析房间模式的游戏,因为在房间模式的游戏中,房间A的数据不会发送到房间B的玩家,会减少大量的数据发送量。假设一个房间有5个玩家,还是按上面的同步方式,一个房间需要发送的数据是(5-1)* 640 * 5=12.5kB。1M的带宽可以运行 1024/8/12.5 = 10.24个房间,得出1M的带宽可以带动10 * 5 = 50个玩家。
从上面两种游戏模式可以看出,一个玩家的数据同步到其他玩家的数量越少,服务器承载的玩家数量也就越多。
为了在mmo类型游戏中实现近似房间模式的数据同步效果,通常使用的思路是AOI(Area Of Interest)翻译过来就是“感兴趣的区域”。服务器只会同步你周边多少半径以内的玩家给你,太远的一是玩家屏幕看不到没有意义,二是同步太多的玩家对于服务器压力成倍数上涨。另外一中减少服务端带宽的策略是,把要同步到客户端的数据合并成一个消息包,这样可以减少发送冗余信息,同时当一个包有足够长度才能有效的进行压缩。
常见的AOI算法有:九宫格、灯塔算法、十字链表算法、四叉树算法等等,Mirror中有一个案例CCU,里面使用了一种空间划分的方案。
常见的压缩算法有:zlib、snappy、lz4、lzw。
如果超过带宽承载能力会有什么后果,我用unity商店的mirror插件测试了一下,当客户端数量比较少的情况下同步状况良好,但超过10个客户端的时候会出现明显的掉帧情况。
AOI算法实现和原理 https://zhuanlan.zhihu.com/p/56114206
蹭个热度看看ChatGPT怎么回答的。