【问题标题】:Multiplayer game server model - world replication and object updates多人游戏服务器模型 - 世界复制和对象更新
【发布时间】:2012-08-24 08:02:11
【问题描述】:

我目前正在尝试为少数玩家(我认为少于 20 )。我将 TCP 套接字用于需要保证交付的数据包(即:聊天消息、登录和注销请求、ping 数据包等),将 UDP 用于不一定需要交付的所有内容,因为只有最后一个通过的数据包是重要(即:用户输入、游戏世界和对象更新等)。

我应该在这里提一下,我的游戏世界是什么样子的。每个对象服务器端都有其 id、角色和所有者成员。 Id 基本上是客户端的标识符,因此,一旦我向他们发送对象更新,他们就知道要更新哪个对象。 Owner是关于对象所有者的信息,即:控制actor的玩家。一旦玩家失去连接/注销,我用它来删除孤立的对象。然而,大多数对象都将此值设置为 Server。最后角色决定对象对客户是否重要。这可以设置为 ServerSide(对于不需要复制到客户端的对象,因为它们仅用于服务器端游戏状态计算),RelevantToOwner(此对象仅复制到其所有者,即:玩家私人库存不需要复制给所有人)、RelevantToList(对象被复制给列表中的所有玩家,即:我有对象可见的玩家列表,我只复制给他们)和 RelevantToAll(复制给所有人)。

当用户发送登录数据包时,我检查我是否有空闲插槽,如果有,那么我将世界复制给他(发送当前世界状态 - 每个没有将角色设置为 ServerSide 或 RelevantToList 的对象 - 当然除非客户端是在该对象的列表中)。

然后在服务器游戏状态更新循环的每次迭代之后,我发送完全相同的东西 - 整个世界状态。

当用户发送注销数据包时,我将他从登录的客户端中删除,释放插槽,并从游戏世界中删除所有孤立对象(以该用户为所有者的对象)。

这是我的问题:

  • 这个模型适合实时多人游戏还是我做错了?
  • 有没有办法减少初始世界复制后发送的数据包数量(即:仅更新自上次迭代以来状态发生变化的对象。我已经考虑过了,到目前为止我遇到了一个大问题使用这种方法 - 如果来自先前迭代的 UDP 数据包丢失并且对象的状态在后续迭代中没有改变,则对象将不会在播放器端更新。)
  • 如何将多个对象更新打包到一个数据包中(我目前正在发送一个效率低下且可能非常错误的对象/数据包。
  • 谁能给我指出一些简单客户端/服务器游戏的工作示例(来源会很好),以便我了解专业人士是如何做到的? C++ 或 C 会很好,但 Java / C# / Python 也很好。

【问题讨论】:

  • 顺便说一句,如果这是一个作业,你真的应该添加作业标签

标签: c++ replication real-time multiplayer


【解决方案1】:

这在很大程度上取决于您所谈论的游戏类型 - 例如:我在基于文本的垃圾游戏中做大致相同的事情。我的更新很简单,到达时发送房间详细信息。在更改时,发送消息说人/对象来/去。完成。

UDP 是大多数在线游戏的工作方式,只是因为它们需要处理 100k+ 的连接。 UDP 丢失通常是玩家在游戏中“扭曲”的原因。如果你有 20 个人,并且可以保证这一点,那么坚持使用 tcp 会有所帮助。

你需要把他们送到全世界​​吗?你的世界不是由区域/房间组成的吗?通常您发送较小的区域。例如,它还取决于您应该发送的对象上的数据量。如果一个玩家有一个物品栏,没有必要将它发送给所有其他玩家,除非他们特别要求 - 穿着的物品(如果是视觉游戏,那么是的,你需要或者它画错了)

仅仅因为我们现在有更快的连接并不意味着我们不应该考虑有些人不考虑。您应该尝试只发送更新并让客户端保持自己的状态,然后在更改区域并重新加载区域时确保同步。

要将对象更改打包到一个数据包中,我很可能会猜测它的位置更改,例如坐标和可用性,例如,人拿起物品。有一个 upate 结构,item_id,update_type,update_values[],然后你就可以发送一大块更新了。

您是基于文本还是更多 mmorg 类型?基于文本的我可以说 google tinymuck,或者 tinymush,tinymud,有很多,图形的?那更难,你可以查找一些旧的 EQ 代码和魔兽模拟器也许..

【讨论】:

  • 这很大程度上取决于您所谈论的游戏类型 它可能是简单的基于图块的 MUD。还不确定...你的世界不是由区域/房间组成的吗? 实际上,它是一个巨大的区域自动取款机。 通常你发送较小的区域。这就是我添加角色成员的原因 - 现在我只发送与给定客户端相关的对象。
  • 还有我问的所有其他问题吗?
  • 有一个 upate 结构,item_id,update_type,update_values[],然后你可以发送一个更新块。你说的块是指由几个这样的结构组成的数据包,对吧?另外,如果你有 20 个人,并且可以保证这一点,那么坚持使用 tcp 会有所帮助。 不幸的是,我无法选择协议,这是任务的一部分。
  • 很好,但是作为一个社区,你们问了一堆模糊的问题,没有回答一些具体的问题。你仍然可以用 udp 做同样的理论,当然你不保证收据,但这很好。你还没有真正回答关于发送世界数据的问题......如果你坚持一个巨大的区域,那么你唯一能做的就是只从可见区域发送数据。
  • 我什么都不坚持。只是现在已经完成了,我并不是说我将来不会改变它。另外,正如我之前所说,我目前只发送与给定客户端相关的对象。但我想世界分为区域会有它的优点。我假设我能够独立更新区域状态,然后仅将来自玩家所在区域的相关对象发送给玩家。另外,我正在查看 TinyMUX atm 的来源,我想我会有一些东西要阅读一会儿。
猜你喜欢
  • 1970-01-01
  • 2011-06-21
  • 1970-01-01
  • 2011-07-05
  • 2014-09-17
  • 2014-09-17
  • 1970-01-01
  • 1970-01-01
  • 2010-11-02
相关资源
最近更新 更多