提供实时游戏状态更新的服务器

| 目前,我的游戏服务器很小(一个区域,约有50个AI),每次发送状态更新数据包(UDP)时,它都会向每个客户端发送完整状态。这将创建约1100字节的数据包大小。它发送的几乎所有实体的以下信息:
int uid
int avatarImage
float xPos
float yPos
int direction
int attackState
24 bytes
编辑:更有效的结构
int uid
byte avatarImage
float xPos
float yPos
byte direction & attackState
14 bytes
但我最终需要向实体发送更多信息。例如,我要添加到此:
float targetXPos
float targetYPos
float speed
由于需要为每个实体发送更多数据,因此我正在快速接近并且很可能已经通过了数据包的最大大小。因此,我试图考虑一些解决问题的方法: 1)只需建立状态更新数据包,直到我用完房间,然后将其余的都省去即可。客户端视图非常糟糕。并非真正的选择。 2)仅将N个最近实体的数据发送给客户端。这就要求每个状态更新我都为每个客户端计算最接近的N。这可能非常耗时。 3)一些如何设计数据包,以便我可以为同一更新发送多个数据包。当前,客户端假定数据包具有以下结构:
int currentMessageIndex
int numberOfPCs
N * PC Entity data
int numberOfNPCs
N * NPS Entity data
然后,客户端将获取此新数据,并完全覆盖其状态副本。由于数据包是完全独立的,即使客户端错过了数据包,也可以。我不确定如何将多个数据包用于同一更新,因为如果我错过了其中一个,那又会怎样呢?我无法用更新的部分状态覆盖完整的过时状态。 4)仅发送更改的实际变量。例如,对于每个实体,我添加一个int,它是每个字段的位掩码。不需要每次更新都发送诸如速度,目标,方向和avatarImage之类的信息。我仍然回到有关客户端丢失实际上确实需要更新这些值之一的数据包的情况的问题。我不确定这有多重要。这也需要在客户端和服务器端进行一些更多的计算来创建/读取数据包,但不要太多。 还有更好的主意吗?
已邀请:
我会选择4号和2号。 如您所知,通常最好只发送更新而不是完整的游戏状态。但是请确保您始终发送绝对值而不是增量,以便在丢弃数据包时不会丢失任何信息。您可以在客户端使用推算来使动画在恶劣的网络条件下尽可能平滑。 您必须为此进行仔细设计,以使数据包丢失不是至关重要的。 至于数字2,如果您为其设计,则不必花费时间。例如,您可以将游戏区域划分为正方形网格,其中每个实体始终位于一个特定的正方形中,并让游戏世界对此进行跟踪。在那种情况下,计算9个环绕网格中的实体是O(1)运算。
通常使用航位推算或预测性合同算法解决此类系统。您不能依赖于所有客户端同时获取更新,因此您需要根据先前已知的值预测位置,然后根据服务器生成的结果验证这些预测。
我遇到的问题是发送增量更新(基本上是您的第4个选项),该数据可能是乱序的,也可能是旧的,具体取决于服务器的并发程度,基本上是多个客户端同时更新服务器的竞争状况。 我的解决方案是向所有客户端发送更新通知,并为每个已更新的项目设置一个位掩码。 然后,客户端根据位掩码请求特定数据的当前值。这还允许客户端仅请求其感兴趣的数据。 这样做的好处是它避免了竞争情况,并且客户总是获得最新的价值。 缺点是需要往返才能获得实际值。 更新以演示我要提出的观点。 假定有四个客户A,B,C,D。 A和B将同时更新发送到服务器Xa和Xb上的可变状态X。由于B进入的时间比A稍晚,因此服务器上X的最终状态为X = Xb。 服务器将更新后的状态发送给所有客户端,因此C和D会获取X的更新状态,因为交付顺序不确定,C会获得Xa然后Xb,D会得到Xb然后Xa,因此在这一点上客户端C和客户端D对X的状态有不同的想法,一个反映服务器拥有的内容,另一个反映服务器没有的内容,它已弃用(或旧的)数据。 另一方面,如果服务器只是向所有客户端发出X更改的通知,则C和D将获得两个X的状态更改通知。它们都请求X的当前状态,并且最终都以服务器上X的最终状态是Xb。 由于状态通知的顺序无关紧要,因为其中没有数据,并且客户端在每个通知上均发出更新状态的请求,因此它们都以一致的数据结尾, 我希望我想指出的观点更加清楚。 是的,这确实增加了延迟,但是设计人员必须决定更重要的是延迟,还是让所有客户端反映相同的可变数据状态。这将取决于数据和游戏。

要回复问题请先登录注册