Java 通过网络高效地发送玩家移动

Java 通过网络高效地发送玩家移动,java,networking,Java,Networking,我正在使用Slick2D制作一个Java游戏,并使用Kryonet进行多人游戏。当播放器按W、a、S或D键时,它们移动,PlayerMovePacket对象通过网络(通过UDP)发送到服务器。然后服务器将此信息发送给其他客户端,这些客户端根据数据包中的信息设置该玩家位置的本地副本 以下是PlayerMovePacket的代码: public class PlayerMovePacket { public Vector2f pos; public int clientID; public Pl

我正在使用Slick2D制作一个Java游戏,并使用Kryonet进行多人游戏。当播放器按W、a、S或D键时,它们移动,PlayerMovePacket对象通过网络(通过UDP)发送到服务器。然后服务器将此信息发送给其他客户端,这些客户端根据数据包中的信息设置该玩家位置的本地副本

以下是PlayerMovePacket的代码:

public class PlayerMovePacket {

public Vector2f pos;
public int clientID;

public PlayerMovePacket() {
    pos = new Vector2f(0, 0);
    clientID = -1;
}

public PlayerMovePacket(Vector2f v, int id) {
    pos = v;
    clientID = id;
}
}
这样做,客户端/服务器会因太多消息而过载,并崩溃。我看到的另一个选择是,我只会每隔几毫秒发送一次玩家的位置。然而,客户在大多数情况下都不会知道球员的最新位置,而且动作也会很紧张


关于如何防止服务器过载,你有什么想法吗?

我想你可以每隔几毫秒发送一次位置信息,并做一些客户端预测,以使其不那么紧张。

添加一个阈值,你是否真的需要为每一个小动作发送移动数据

另一种方法是按照建议每隔几毫秒聚合一次。如果玩家移动了3次(或3次动作),您可以将移动内容聚合到一个数据包中,并为自己保存一些网络I/O。这实际上取决于游戏以及您的一致性保证是什么。在大多数情况下,每25-50毫秒发送一次数据是可以接受的,因为您无论如何都无法更快地感知到变化


@jussi还提到,您可以尝试预测客户端的移动,并在每次收到新的球员位置数据包时进行简单的补偿,这也是可以接受的,并且使用得相当广泛。我会提醒你,尽量使它变得非常复杂,因为它会使游戏变得更加跳跃或滞后,但简单的直线轨迹就可以了。您可以在许多游戏中看到这样的例子,在这些游戏中,您可以看到断开连接的人有时在游戏中原地运行或遇到对象,直到服务器意识到他们实际上已断开连接,并且这样的事情是可以接受的,因为您需要足够高的阈值,延迟峰值不会导致客户端上的服务器完全断开连接。

+1客户端预测,尽管如果实现错误,可能会使它更加不稳定。这是很正常的。考虑一下玩滞后的电子游戏。当你开始以高延迟落后并且你“落后”时,你的角色通常会继续他们当前的路径/轨迹/速度,直到服务器更新,此时你会被扔回正确的位置。但客户端或本地控制台游戏通常会根据您最近的移动情况继续预测您的去向。@Kyle是的,这就是为什么我提到做错了,它可能看起来相当滞后(特别是在某些游戏中,滞后补偿使游戏更难玩咳嗽任务呼叫咳嗽)。如果每个移动都很重要,请不要使用UDP,因为它可能无法到达端点。