当前位置: 首页 > 知识库问答 >
问题:

在网络游戏中定期将输入立即发送到服务器或输入缓存中

罗绪
2023-03-14

我正在编写一个网络化多人游戏,其中所有影响游戏性的输入都被保存并作为队列中的事件处理,以便能够在给定一组事件的情况下重新生成所有动作。例如:用户按下左箭头按钮;然后,将带有“Press Left”的事件添加到队列中,以当前时间t保存,然后使用固定的时间步执行http://gafferongames.com/game-physics/fix-your-timestep/.

这些事件也被发送到服务器,服务器定期将从客户端接收到的一组事件发送到所有其他客户端,比方说每100毫秒。游戏是一个快节奏的多人游戏,因此使用实体插值,如下所述:http://www.gabrielgambetta.com/fpm3.html

将这些事件发送到服务器的最佳方式是什么?立即单独发送每个事件,或者在客户端上保存一个“事件缓存”,并且在客户端上定期向服务器发送一个新事件列表,这样做有意义吗?我担心,如果我立即发送事件,事件的同步可能会出现问题,或者可能会因网络上的消息过多而堵塞。

事件缓存的问题是,我必须为所有内容添加额外的延迟,因为事件只能从客户端每隔n秒发送一次,然后从服务器每隔n秒发送一次。对于玩家来说,从输入到执行,允许的延迟是什么?

我希望我已经说清楚了。

共有1个答案

关志勇
2023-03-14

可接受的延迟实际上取决于游戏的类型。对于快节奏游戏(例如FPS),您希望延迟尽可能低,我认为在这种情况下,任何非即时的延迟都是不可接受的。

您可能应该以固定的时间间隔向服务器发送更新,但如果可以的话,将它们降低到15-20毫秒。在更新间隔之间,您将缓冲命令(事件)。我不知道这到底是什么样的游戏,但可能最好在客户端计算对象状态(并立即显示)并将状态发送到服务器进行验证。例如,如果我们谈论的是玩家运动,您将例如发送当前坐标和速度矢量,服务器将检查提供的新坐标是否有效(是否有可能从上一点到达那里)。与此同时,您将在客户端中显示新的坐标,并在服务器响应后根据需要更正它们。

要以这种速率进行网络连接,最好的选择是UDP。因为它是无连接的,所以您需要自己处理掉的或无序的数据包。根据游戏的不同,您可以将命令分为必须可靠传输的命令和不可靠传输的命令。可以以更大的间隔(例如100ms)发送来自服务器的响应。回到玩家移动的例子,如果您每15毫秒发送一次坐标(让sat位于t、t 1、t 2),如果您在t 1丢弃数据包,您仍然可以插入t和t 2的值(因为服务器将在100毫秒的间隔内响应),这样就可以不可靠地传输这类数据。但如果玩家施法,使用物品或类似物品,你需要确保该消息到达服务器。

您对同步和数据包丢失的担忧是有道理的,但在这两种情况下都可能发生(并且会不时发生)。无论如何,我认为丢弃一个包含一个或两个事件的数据包(间隔较小)比丢弃一个包含数十个事件的数据包要好。此外,在大多数使用QoS的网络配置中,较小的数据包不太可能被丢弃或延迟。此外,根据发送到服务器的数据,所需的带宽可能根本没有那么大。

这是一个相当广泛的问题,所以这些只是一些需要考虑的问题。其中一些可能在您提供的链接中进行了解释,您也可以阅读以下内容

 类似资料:
  • 1.1.1. inputflinger 1.1.1. inputflinger inputflinger为输入事件服务,基于android源码修改。 源码路径:robot/frameworks/native/services/inputflinger 此服务为系统级服务,不允许第三方应用直接调用,不支持多实例运行。可由类似AMS(Apps Manager Service)级别的系统进程注册inpu

  • 问题:安东尼娅和大卫在玩游戏。每位选手以100分开始。游戏使用标准的六面骰子,分回合进行。在一个回合中,每个玩家掷一个骰子。下滚的玩家失去了在较高的骰子上显示的点数。如果两个玩家掷相同的号码,任何一个玩家都不会丢分。写一个程序来确定最后的分数。 以下是我目前掌握的信息: 我知道我只具体要求了一件事,但有人能完成这个挑战并解释最好的方法吗?

  • 技术面面完了,一个小时 1、自我介绍 2、项目介绍,介绍了简历上的一个高并发内存池项目,说的磕磕巴巴的 3、介绍其它几个项目 4、用哪几种语言,C++与Python的区别 5、面向对象三大特性,就让我我介绍了一下,我还以为要问多态中的 6、进程地址空间中的有哪些分区,堆栈、代码、常量、共享内存 7、进程间如何通信,共享内存忘说了 8、网络的那些UDP/TCP,我没学过直接说不会 9、哪些数据结构,

  • 问题内容: 我正在用Java编写游戏,现在是Swing + JOGL-一个带有GLCanvas的JFrame。 我使用etc.事件()处理输入,但似乎无法正常工作: 当我同时按下3个以上的键时,它们无法正确注册 -显然这是键盘的错误,我必须找到替代的控制方案。 窗口丢失后,重新获得焦点,输入完全停止工作… 我究竟做错了什么? 有没有更好的方法来处理Java中的键盘输入? (除非我别无选择,否则我不