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

Java 提供实时游戏状态更新的服务器,java,networking,client-server,Java,Networking,Client Server,目前我的游戏服务器很小(一个区域和~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 direct

目前我的游戏服务器很小(一个区域和~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作为位掩码。速度、目标、方向和虚拟形象等信息不需要在每次更新时发送。我仍然要回到问题上来,如果客户端丢失了一个确实需要更新其中一个值的数据包,会发生什么情况。我不确定这会有多重要。这也需要在客户端和服务器端进行更多的计算来创建/读取数据包,但不会太多


还有更好的主意吗?

我会选择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

由于状态通知的顺序是不相关的,因为其中没有数据,并且客户端在每个通知上发出更新状态的请求,它们最终都会得到一致的数据

我希望这能更清楚地说明我想表达的观点


是的,它确实会增加延迟,但设计师必须决定什么更重要,延迟还是让所有客户端反映可变数据的相同状态。这将取决于数据和游戏。

这种类型的系统通常使用or算法来解决。你不能依赖于所有客户端同时获得更新o您需要根据先前已知的值预测位置,然后根据服务器生成的结果验证这些预测。

我喜欢您的第四个想法。但是,如果任何信息相互关联(如速度和方向)。确保这些数据一起发送。如果客户端在任何一种情况下丢失数据包…它仍将丢失更新…数据是一次性发送还是仅在数据更改时发送。压缩呢?还是某种自定义编码?如果您事先知道某些值的范围,您可以承受每个字段上的某些位丢失…我喜欢第4个也是。除了发送更新数据包外,您还可以根据客户机的请求发送整个_状态数据包。当您包括