我正在制作客户端服务器 MMO 风格的游戏。到目前为止,我已经设置了框架,以便服务器和客户端相互交互以提供状态更新。服务器维护游戏状态并定期计算下一个状态,然后每隔一段时间(每 n 毫秒)将新状态发送给所有客户端。用户可以在客户端查看此新状态并使用react。然后将这些操作发送回服务器进行处理并发送出去进行下一次更新。
明显的问题是这些更新在服务器和客户端之间传输需要时间。如果客户端开始攻击敌人,当更新返回到服务器时,服务器很可能已经将游戏状态推进到敌人不再在同一地点并且超出范围的程度。
为了解决这个问题,我一直在努力想出一个好的解决方案。我看过以下内容,它对一些人有所帮助,但并不完全:Mutli Player Game synchronization .我已经得出结论,除了传输游戏的当前状态之外,我还可以传输其他信息,例如方向(或 AI 移动的目标位置)和速度。由此,我有一部分需要在客户端“猜测”实际状态是什么(如服务器所见),方法是将游戏状态推进到 future n 毫秒。
问题是确定状态进展的时间量,因为这将取决于服务器和客户端之间的滞后时间,这可能会有很大差异。另外,我应该将游戏状态推进到客户端查看它时的当前状态(即仅考虑更新到达客户端所花费的时间)还是我应该将其推进到足够远以便发送响应时返回到服务器,到那时它就是正确的状态(考虑往返旅程)。
有什么建议吗?
重申一下:
1) 计算发送和接收之间的时间量的最佳方法是什么?
2) 我应该将客户端状态推进到足够远以计入整个往返行程,还是仅计入从服务器到客户端获取数据所需的时间?
编辑:到目前为止我想出了什么
因为我已经有很多数据包在客户端和服务器之间来回传输,如果必须的话,我不想增加流量。目前,客户端向服务器发送状态更新数据包 (UDP) 约 150 毫秒(仅当某些内容发生变化时),然后服务器接收并处理这些数据包。目前,服务器不对这些数据包发送任何响应。
首先,我会让客户尝试估计他们的滞后时间。我会将它默认为 50 到 100 毫秒。我建议大约每 2 秒(每个客户端)服务器将立即响应其中一个数据包,在特殊的定时更新数据包中发回数据包索引。如果客户端收到计时数据包,它会使用索引来计算这个数据包发送的时间,然后使用数据包之间的时间作为新的滞后时间。
这应该可以让客户端合理地了解他们的滞后情况,而不会产生过多的网络流量。
听起来可以接受,还是有更好的方法?这仍然没有回答问题二。
最佳答案
首先,仅供引用,如果您担心少于 1 秒的延迟,您就已经开始脱离 MMO 的现实延迟领域。所有大型 MMO 处理此问题的方式基本上是同时运行两个不同的“游戏”——有一个底层游戏引擎处理所有数学、角色状态、应用数值变化,然后是图形客户端。
第一个“游戏”,即数学和计算,在概念上更接近传统的主机游戏(如旧版 MUD)。考虑来回传递的消息,具有非常高的 ACID 隔离度。这些消息更关心准确性,但您应该假设这些消息可能需要 1-2 秒(或更长时间)来处理和更新。这是确保正确计算生命值等的“规则律师”。
第二个“游戏”是图形客户端。这个客户端真正专注于保持事情发生得比第一个游戏快得多的错觉,同时也将即将到来的事件与图形外观同步。这个图形客户端通常只是简单地弥补了一些不重要的事情。此客户端负责 30 fps+ 图形。这就是为什么很多这些图形客户端使用一些技巧,例如在用户按下按钮时启动攻击动画,但直到第一个游戏解决攻击时才真正解决动画。
我知道这与您的问题的字面解释有点不同,但是一旦您离开网络上并排放置的两台机器,100 毫秒真的很乐观...
关于java - 同步客户端-服务器游戏状态,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5690899/
我正在尝试使用ruby和Savon来使用网络服务。测试服务为http://www.webservicex.net/WS/WSDetails.aspx?WSID=9&CATID=2require'rubygems'require'savon'client=Savon::Client.new"http://www.webservicex.net/stockquote.asmx?WSDL"client.get_quotedo|soap|soap.body={:symbol=>"AAPL"}end返回SOAP异常。检查soap信封,在我看来soap请求没有正确的命名空间。任何人都可以建议我
我需要在客户计算机上运行Ruby应用程序。通常需要几天才能完成(复制大备份文件)。问题是如果启用sleep,它会中断应用程序。否则,计算机将持续运行数周,直到我下次访问为止。有什么方法可以防止执行期间休眠并让Windows在执行后休眠吗?欢迎任何疯狂的想法;-) 最佳答案 Here建议使用SetThreadExecutionStateWinAPI函数,使应用程序能够通知系统它正在使用中,从而防止系统在应用程序运行时进入休眠状态或关闭显示。像这样的东西:require'Win32API'ES_AWAYMODE_REQUIRED=0x0
我想安装一个带有一些身份验证的私有(private)Rubygem服务器。我希望能够使用公共(public)Ubuntu服务器托管内部gem。我读到了http://docs.rubygems.org/read/chapter/18.但是那个没有身份验证-如我所见。然后我读到了https://github.com/cwninja/geminabox.但是当我使用基本身份验证(他们在他们的Wiki中有)时,它会提示从我的服务器获取源。所以。如何制作带有身份验证的私有(private)Rubygem服务器?这是不可能的吗?谢谢。编辑:Geminabox问题。我尝试“捆绑”以安装新的gem..
我真的很习惯使用Ruby编写以下代码:my_hash={}my_hash['test']=1Java中对应的数据结构是什么? 最佳答案 HashMapmap=newHashMap();map.put("test",1);我假设? 关于java-等价于Java中的RubyHash,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/22737685/
最近,当我启动我的Rails服务器时,我收到了一长串警告。虽然它不影响我的应用程序,但我想知道如何解决这些警告。我的估计是imagemagick以某种方式被调用了两次?当我在警告前后检查我的git日志时。我想知道如何解决这个问题。-bcrypt-ruby(3.1.2)-better_errors(1.0.1)+bcrypt(3.1.7)+bcrypt-ruby(3.1.5)-bcrypt(>=3.1.3)+better_errors(1.1.0)bcrypt和imagemagick有关系吗?/Users/rbchris/.rbenv/versions/2.0.0-p247/lib/ru
在Rails4.0.2中,我使用s3_direct_upload和aws-sdkgems直接为s3存储桶上传文件。在开发环境中它工作正常,但在生产环境中它会抛出如下错误,ActionView::Template::Error(noimplicitconversionofnilintoString)在View中,create_cv_url,:id=>"s3_uploader",:key=>"cv_uploads/{unique_id}/${filename}",:key_starts_with=>"cv_uploads/",:callback_param=>"cv[direct_uplo
当我的预订模型通过rake任务在状态机上转换时,我试图找出如何跳过对ActiveRecord对象的特定实例的验证。我想在reservation.close时跳过所有验证!叫做。希望调用reservation.close!(:validate=>false)之类的东西。仅供引用,我们正在使用https://github.com/pluginaweek/state_machine用于状态机。这是我的预订模型的示例。classReservation["requested","negotiating","approved"])}state_machine:initial=>'requested
我想在Ruby中创建一个用于开发目的的极其简单的Web服务器(不,不想使用现成的解决方案)。代码如下:#!/usr/bin/rubyrequire'socket'server=TCPServer.new('127.0.0.1',8080)whileconnection=server.acceptheaders=[]length=0whileline=connection.getsheaders想法是从命令行运行这个脚本,提供另一个脚本,它将在其标准输入上获取请求,并在其标准输出上返回完整的响应。到目前为止一切顺利,但事实证明这真的很脆弱,因为它在第二个请求上中断并出现错误:/usr/b
您如何在Rails中的实时服务器上进行有效调试,无论是在测试版/生产服务器上?我试过直接在服务器上修改文件,然后重启应用,但是修改好像没有生效,或者需要很长时间(缓存?)我也试过在本地做“脚本/服务器生产”,但是那很慢另一种选择是编码和部署,但效率很低。有人对他们如何有效地做到这一点有任何见解吗? 最佳答案 我会回答你的问题,即使我不同意这种热修补服务器代码的方式:)首先,你真的确定你已经重启了服务器吗?您可以通过跟踪日志文件来检查它。您更改的代码显示的View可能会被缓存。缓存页面位于tmp/cache文件夹下。您可以尝试手动删除
我正在尝试使用boilerpipe来自JRuby。我看过guide从JRuby调用Java,并成功地将它与另一个Java包一起使用,但无法弄清楚为什么同样的东西不能用于boilerpipe。我正在尝试基本上从JRuby中执行与此Java等效的操作:URLurl=newURL("http://www.example.com/some-location/index.html");Stringtext=ArticleExtractor.INSTANCE.getText(url);在JRuby中试过这个:require'java'url=java.net.URL.new("http://www