多人游戏同步
我实现了服务器/客户端架构,其中所有状态更改都发送到函数,经过验证并广播到所有连接的客户端。这工作得相当好,但系统目前无法维持游戏客户端实例之间的同步。
如果服务器和特定客户端之间恰好有 5 秒的延迟,那么他将在其他客户端之后 5 秒收到状态更改,从而使他的游戏状态不同步。我一直在寻找各种方法来实现客户端之间的同步系统,但到目前为止还没有找到太多。
我是网络编程的新手,并不天真地认为我可以自己发明一个工作系统,而无需投入大量时间。然而,我一直以来的想法是保留某种时间系统,因此每个状态更改都将与游戏中的特定时间戳相关联。这样,当客户端收到状态更改时,它会准确地知道更改发生在游戏的哪个时期,并且反过来能够关联滞后。这种方法的问题在于,在n秒的延迟中,游戏将在客户端继续进行,因此客户端必须及时回滚以更新状态更改,这肯定会得到凌乱的。
所以我正在寻找讨论解决该问题的主题或算法的论文。也许我对多人游戏系统如何工作的整个设计是有缺陷的,从某种意义上说,除非从服务器收到概念,否则客户端的游戏实例不应更新?现在,客户端只是在游戏循环中更新自己,假设任何状态都没有改变。
I've a server/client architecture implemented, where all state changes are sent to the function, validated and broadcasted to all clients connected. This works rather well, but the system does not maintain synchronization between the client instances of the game as of now.
If there happened to be a 5 second lag between the server and a particular client then he would receive the state change 5 seconds after the rest of the clients thus leaving him with game state out of sync. I've been searching for various ways to implement a synchronization system between the clients but haven't found much so far.
I'm new to network programming, and not so naive to think that I can invent a working system myself without dedicating a severe amount of time to it. The ideas I've been having, however, is to keep some kind of time system, so each state change would be connected to a specific timestamp in the game. That way when a client received a state change, it would know exactly in which period of the game the changed happened, and would in turn be able to correlate for the lag. The problem with this method is that in those n seconds lag the game would have had continued on the client side, and thus the client would have to rollback in time to update for the state change which definitely would get messy.
So I'm looking for papers discussion the subjects or algorithms that solves it. Perhaps my whole design of how the multiplayer system works is flawed, in the sense that a client's game instance shouldn't update unless notion is received from the server? Right now the clients just update themselves in their game loop assuming that any states haven't changed.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
基本方法是航位推算,这是一个相当不错的方法。关于它的文章可以在这里找到。基本上,它是一种预测算法,用于猜测服务器更新之间的时间实体位置。
有更先进的方法建立在这个概念的基础上,但它是一个很好的起点。
另外,还可以找到源引擎(第一款《半条命》游戏的 Valve 引擎)中如何处理此问题的描述 这里,原理基本上是相同的 - 直到服务器告诉您使用预测算法沿着预期路径移动实体 - 但本文处理这对尝试更深入地拍摄某些东西所产生的影响。
The basic approach to this is something called Dead Reckoning and a quite nice article about it can be found here. Basically it is a predication algorithm for where entities positions will be guessed at for the times between server updates.
There are more advanced methodologies that build on this concept, but it is a good starting point.
Also a description of how this is handled in the source engine (Valve's engine for the first Half Life game) can be found here, the principle is basically the same - until the server tells you otherwise use a prediction algorithm to move the entity along an expected path - but this article handles the effect this has on trying to shoot something in more depth.
我在该领域找到的最佳资源是 Valve Software 的这两篇文章:
The best resources I've found in this area are these two articles from Valve Software:
永远没有办法保证多个视点实时完美同步——物理定律使它不可能。如果太阳现在爆炸了,你怎么能保证半人马座阿尔法星上的观察者能像我们在地球上一样同时看到超新星呢?信息的传播需要时间。
因此,您的选择是要么对所有内容进行准确建模,延迟可能因观看者而异(这就是您当前所拥有的),要么在没有延迟的情况下不准确地对它们进行建模,并在观看者之间广泛同步(这就是预测/航位推算/外推法出现的地方)在)。诸如实时策略之类的较慢的游戏往往采用第一条路线,而较快的游戏则采用第二条路线。
特别是,您永远不应该假设旅行所需的时间是恒定的。这意味着在任何一种模型下,仅仅发送开始和停止消息来移动实体都是不够的。您需要定期发送实际状态的更新(对于更快的游戏,通常每秒几次),以便接收者可以纠正其预测和插值中的错误。
There will never be a way to guarantee perfect synchronisation across multiple viewpoints in real time - the laws of physics make it impossible. If the sun exploded now, how could you guarantee that observers on Alpha Centauri see the supernova at the same time as we would on Earth? Information takes time to travel.
Therefore, your choices are to either model everything accurately with latency that may differ from viewer to viewer (which is what you have currently), or model them inaccurately without latency and broadly synchronised across viewers (which is where prediction/dead reckoning/extrapolation come in). Slower games like real time strategy tends to go the first route, faster games go the second route.
In particular, you should never assume that the time it takes to travel will be constant. This means that merely sending start and stop messages to move entities will never suffice under either model. You need to send periodic updates of the actual state (typically several times a second for faster games) so that the recipient can correct error in its predictions and interpolations.
如果客户端看到事件以服务器提供给他的速度发生,这是正常的方法(我使用过 Ultima Online、KalOnline 和一点魔兽世界的协议),那么这个瞬间的 5 秒延迟只会让他同时接收这 5 秒的事件,并看到这些事件很快或几乎立即过去,因为如果他的输出也延迟,其他玩家会看到他在短距离内“行走”得非常快。之后一切又恢复正常。实际上,除了图形和物理标准化之外,我看不到任何特殊需要使其正确同步,它只是同步自身。
如果你曾经在两台附近的计算机上玩过 Valve 游戏,你会发现他们不太关心诸如“你死亡的确切地点”或“你的尸体飞到哪里”之类的小细节。这完全取决于客户端,并且完全受到延迟的影响,但这无关紧要。
毕竟,落后的玩家必须接受他们的条件,或者关闭他们该死的 eMule。
If client see events happening at the rate the server is feeding him, which is the normal way to do it (I've worked with protocols of Ultima Online, KalOnline and a little bit of World of Warcraft), then this momentaneous 5 secounds delay would just make him receive this 5 secounds of events all at once and see those events passing really fast or near instantly, as other players would see him "walking" really fast for a short distance if his outputs delay too. After that everything flows normally again. Actually, except for graphic and physics normalization, I can't see any special needs to make it synchronize properly, it just synchronize itself.
If you ever played Valve games in two near computers you would notice they don't care much about minor details like "the exact place where you died" or "where you dead body gibs flyed to". It is all up to client side and totally affected by latency, but this is irrelevant.
After all, lagged players must accept their condition, or close their damn eMule.
最好的选择是从未来将更改发送回客户端,从而与其他不存在滞后问题的客户端在同一时间点到达客户端。
Your best option is to send the changes back to the client from the future, thereby arriving at the client at the same point in time it does for other clients that does not have lag problems.